我在 Java 的方法覆盖/重载中发现了这种明显奇怪的行为,这一直让我感到困惑。 Main()
方法中的调用打印出“B_A”,而我希望它是“B_B”。
package one;
public class A {
public void method(A a){ System.out.println("A_A"); }
public void method(B b) { System.out.println("A_B"); }
public void method(){ this.method(this); }
}
package one;
public class B extends A {
public void method(A a) { System.out.println("B_A"); }
public void method(B b) { System.out.println("B_B"); }
public void method(){ super.method(); }
public static void main(String[] args) {
B bb = new B();
bb.method(); //prints B_A, expected B_B
}
}
我把这个过程分解如下:
- 编译器选择类B的方法
method()
- 在运行时,JVM 通过
super()
调用其父类(super class)的方法method()
<- 这个说法是错误的(感谢 Alexey Romanov 和 pvg)。方法的选择,重载方面,总是在编译时完成。也就是说,该方法在运行时之前转换为 .m(A) 。在运行时,选择适当的覆盖方法。this.method(this)
从类 A 中调用,但this
引用类 B 的实例,因此转换为方法method(B b)
类 B.- 为什么调用类 B 的方法
method(A a)
呢?
我的猜测是,当 JVM 在运行时选择子类方法时,它开始查找重载方法表,其中 是固定优先级,首先查找层次结构中具有较高类参数的方法.也就是说,它不会直接进入 B.method(B b)
,而是在这样的表中查找它,并且可以使用第一个兼容方法 - B.method( A a)
- 因为 B 是 A。
另一个想法是类 A 中的调用 this.method(this)
直接调用 B.method(A a)
,但这意味着相同的符号 (this
) 在同一上下文中 可以引用不同的对象。
有人帮忙解决这个问题吗?提前致谢!
最佳答案
this.method(this) gets called from within class A, but this refers to an instance of class B, therefore translating to method method(B b) of class B.
这一步是错误的。请注意,重载 方法(即具有相同名称的多个方法)由编译器解析。在 A
类中,this
的类型为 A
,因此 this.method(this)
调用 method(一个 a)
。然后在运行时 B
的 that 方法的实现被使用。
Another idea is that the call this.method(this) in class A calls B.method(A a) straight out,
不,它只调用method(A a)
。它对 B
一无所知。
but that would imply that the same symbol (this) in the same context could refer to different objects.
它不会也不暗示。
我还会注意到 public void method(){ super.method();
不会影响此问题中的任何内容。B
中的
关于在子类中使用 "super"并在父类(super class)中使用 "this"的 Java 运行时方法选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44072107/