我在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()调用其超类的方法method()
> this.method(this)从类A中调用,但是这引用了类B的实例,因此转换为类B的方法方法(B b).< - 这个语句是错误的(感谢Alexey Romanov和pvg ).方法的选择,即重载方式,总是在编译时完成.也就是说,该方法在运行时转换为.m(A).在运行时,选择适当的重写方法.
>为什么要调用B类的方法方法(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中,它具有类型A,因此this.method(this)调用方法(A a).然后在运行时B使用该方法的实现.
Another idea is that the call this.method(this) in class A calls B.method(A a) straight out,
不,它只调用方法(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中不会影响这个问题中的任何内容.
标签:java,jvm,overloading,this,super
来源: https://codeday.me/bug/20190828/1752145.html