Java 运行时方法选择在子 class 中使用 "super" 并在超级 class 中使用 "this"
Java runtime method selection using "super" in the subclass and "this" in the super class
我在 Java 的 method-overriding/overloading 中发现了这种明显奇怪的行为,这一直困扰着我。 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
}
}
我把这个过程分解如下:
- 编译器选择方法
method()
of class B
- 在运行时,JVM 通过
super()
调用它的 superclass 的方法 method()
this.method(this)
从 class A 中调用,但 this
引用 class B 的实例,因此转换为方法 method(B b)
of class B. <- 这个说法是错误的(感谢 Alexey Romanov 和 pvg)。方法的选择,重载方面,总是在编译时完成。也就是说,该方法在运行时之前转换为 .m(A) 。在运行时,选择正确的覆盖方法。
- 为什么调用的是 class B 的方法
method(A a)
?
我的猜测是,当 JVM 在运行时选择一个 subclass 方法时,它开始查找 table 重载方法,其中 是固定优先级和具有首先查找层次结构中较高 classes 的参数。也就是说,它不会直接找到 B.method(B b)
,而是查找 table 并且第一个兼容方法没问题 - B.method(A a)
- 因为 B 是 A。
另一个想法是 class 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.
这一步错了。请注意,重载 方法(即具有相同名称的多个方法)由编译器解析。在 class A
中,this
具有类型 A
,因此 this.method(this)
调用 method(A a)
。然后在运行时 B
对 的实现使用 方法。
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.
不会也不暗示。
我还会注意到 B
中的 public void method(){ super.method(); }
不会影响此问题的任何内容。
除了上面讨论的答案,
B bb = new B();
bb.method(); // ... 1 ... prints B_A
A ab = new B();
ab.method(); // ... 2 ... prints B_A
A aa = new A();
aa.method(); // ... 3 ... prints A_A
无论第一种情况和第二种情况的引用类型如何,对象都是针对class B
。
method()
调用 bb
和 ab
调用 super.method()
块。
这从 A class
调用 method()
并将它自己的 class 的引用传递给 this.method(this)
即 this.method(A);
这会在 运行 时间调用 B 下的方法 method(A a)
(方法覆盖)。
第三种情况,this.method(this)
调用了classA下的方法method(A a)
。
这发生在编译时本身(方法重载)
我在 Java 的 method-overriding/overloading 中发现了这种明显奇怪的行为,这一直困扰着我。 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
}
}
我把这个过程分解如下:
- 编译器选择方法
method()
of class B - 在运行时,JVM 通过
super()
调用它的 superclass 的方法 <- 这个说法是错误的(感谢 Alexey Romanov 和 pvg)。方法的选择,重载方面,总是在编译时完成。也就是说,该方法在运行时之前转换为 .m(A) 。在运行时,选择正确的覆盖方法。this.method(this)
从 class A 中调用,但this
引用 class B 的实例,因此转换为方法method(B b)
of class B.- 为什么调用的是 class B 的方法
method(A a)
?
method()
我的猜测是,当 JVM 在运行时选择一个 subclass 方法时,它开始查找 table 重载方法,其中 是固定优先级和具有首先查找层次结构中较高 classes 的参数。也就是说,它不会直接找到 B.method(B b)
,而是查找 table 并且第一个兼容方法没问题 - B.method(A a)
- 因为 B 是 A。
另一个想法是 class 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.
这一步错了。请注意,重载 方法(即具有相同名称的多个方法)由编译器解析。在 class A
中,this
具有类型 A
,因此 this.method(this)
调用 method(A a)
。然后在运行时 B
对 的实现使用 方法。
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.
不会也不暗示。
我还会注意到 B
中的 public void method(){ super.method(); }
不会影响此问题的任何内容。
除了上面讨论的答案,
B bb = new B();
bb.method(); // ... 1 ... prints B_A
A ab = new B();
ab.method(); // ... 2 ... prints B_A
A aa = new A();
aa.method(); // ... 3 ... prints A_A
无论第一种情况和第二种情况的引用类型如何,对象都是针对class B
。
method()
调用 bb
和 ab
调用 super.method()
块。
这从 A class
调用 method()
并将它自己的 class 的引用传递给 this.method(this)
即 this.method(A);
这会在 运行 时间调用 B 下的方法 method(A a)
(方法覆盖)。
第三种情况,this.method(this)
调用了classA下的方法method(A a)
。
这发生在编译时本身(方法重载)