【问题标题】:Java method call overloading logicJava方法调用重载逻辑
【发布时间】:2010-01-05 14:02:16
【问题描述】:

对于下面的代码,为什么会打印 A、B?我希望它能够打印 B,B。 另外,JVM执行的方法调用是动态评估还是静态评估?

public class Main {
    class A {

    }

    class B extends A {

    }

    public void call(A a) {
        System.out.println("I'm A");
    }

    public void call(B a) {
        System.out.println("I'm B");
    }


    public static void main(String[] args) {

        Main m = new Main();
        m.runTest();
    }

    void runTest() {
        A a = new B();
        B b = new B();

        call(a);
        call(b);
    }

}

【问题讨论】:

    标签: java jvm overloading


    【解决方案1】:

    重载由编译器静态决定。 覆盖是在执行时完成的,但这不是这里的一个因素。

    a的静态类型为A,所以第一个方法调用解析为call(A a)

    【讨论】:

    • 谢谢,那么动态评估是什么?
    • @Maxim Veksler:覆盖 - 由目标对象的 实际 类型而不是编译时类型确定。
    【解决方案2】:

    由于此时您的对象的类型为A,因此调用带有参数A 的方法。所以是的,它是静态地确定的。

    这是为了避免歧义。您的 B 也是 A - 但不能同时调用这两种方法。

    【讨论】:

      【解决方案3】:

      BA 的子类。由于您实例化了B,但将其分配给类型为A 的变量,所有B 细节都将“丢失”,因此call(a) 将被分派到call(A, a) 并打印“A”。

      【讨论】:

      • 这有点误导。名为a 的对象仍保留“其所有B 细节” - 例如调用a.getClass().getSimpleName() 将返回“B”。只是正如 Jon 指出的那样,重载是在编译时由 reference 的类型决定的。在这种情况下,编译器并不“知道”a 实际上是B 的一个实例,因此它编译了对call(A a) 方法的调用。但是a 仍然B 的一个实例。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-12
      • 2010-09-30
      • 1970-01-01
      • 2012-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多