在子类中使用 "super"并在父类(super class)中使用 "this"的 Java 运行时方法选择

标签 java jvm this super overloading

我在 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        
    } 
}

我把这个过程分解如下:

  1. 编译器选择类B的方法method()
  2. 在运行时,JVM 通过super()调用其父类(super class)的方法method()
  3. this.method(this) 从类 A 中调用,但 this 引用类 B 的实例,因此转换为方法 method(B b) 类 B. <- 这个说法是错误的(感谢 Alexey Romanov 和 pvg)。方法的选择,重载方面,总是在编译时完成。也就是说,该方法在运行时之前转换为 .m(A) 。在运行时,选择适当的覆盖方法。
  4. 为什么调用类 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)。然后在运行时 Bthat 方法的实现被使用。

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/

相关文章:

c# - 在C#中访问成员时 `this`关键字是可选的吗?

java - 与 Android 操作系统类似,对 JVM 内存消耗进行基准测试

java - Thread.currentThread() 性能

javascript - 初始化对象属性

java - 在kotlin中将接口(interface)定义为接口(interface)的属性并在接口(interface)实现中提供具体的实现是行不通的

macos - 修改我的 OSx 系统上的 Idea vm 内存选项没有改变任何东西

javascript - "this"内部对象

java - 如何持久化 java.util.Currency 之类的类?

java.net.URISyntaxException : Expected authority at index 7: http://

java - 为什么在使用Eclipse IDE播放.wav声音文件时出现此错误?