简体   繁体   English

使用子类中的“super”和超类中的“this”选择Java运行时方法

[英]Java runtime method selection using “super” in the subclass and “this” in the super class

I found this apparently odd behaviour in method-overriding/overloading of Java, that has been boggling my mind. 我在Java的方法覆盖/重载中发现了这种显然很奇怪的行为,令人难以置信。 The call in the Main() method prints out " B_A ", while I would expect it to be " B_B ". 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        
    } 
}

I break down the process as the following: 我按以下方式分解了这个过程:

  1. The compiler selects method method() of class B 编译器选择B类的方法method()
  2. During runtime, JVM calls method method() of its superclass via super() 在运行时,JVM通过super()调用其超类的方法method() super()
  3. 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. <- this statement is wrong (thanks Alexey Romanov and pvg). this.method(this)被从类A内调用,但this是指类B的一个实例,因此转换到方法method(B b)类B的 < - 这个说法是错误的(感谢阿列克谢罗曼诺夫和PVG)。 Selection of methods, overloading-wise, is always done at compile time. 方法的选择,即重载方式,总是在编译时完成。 That is, that method translates to .m(A) before runtime. 也就是说,该方法在运行时转换为.m(A)。 At runtime, the proper overriding method is chosen. 在运行时,选择适当的重写方法。
  4. Why is the method method(A a) of class B being invoked, instead? 为什么要调用B类的方法method(A a)呢?

My guess is that the JVM, when it selects a subclass method during runtime, starts looking up into a table of overloaded methods, where is a fixed precedence and the methods with a arguments of higher classes in the hierarchy are looked up first. 我的猜测是,JVM在运行时选择子类方法时,会开始查找重载方法的表,其中是一个固定的优先级,并且首先查找层次结构中具有更高类的参数的方法。 That is, it doesn't go straight for B.method(B b) , instead it looks it up into such a table and it's ok with the first compatible method - B.method(A a) - as B is A. 也就是说,它不直接用于B.method(B b) ,而是将其查找到这样的表中,并且可以使用第一个兼容方法B.method(A a) - 因为B是A.

Another idea is that the call this.method(this) in class A calls B.method(A a) straight out, but that would imply that the same symbol ( this ) in the same context could refer to different objects. 另一个想法是,在类A中调用this.method(this)直接调用B.method(A a) ,但这意味着相同上下文中的相同符号( this )可以引用不同的对象。

Any help sorting this out? 任何帮助整理出来的? Thanks in advance! 提前致谢!

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. this.method(this)从类A中调用,但这引用了类B的实例,因此转换为类B的方法方法(B b)。

This step is wrong. 这一步是错误的。 Note that overloaded methods (that is, multiple methods with same name) are resolved by the compiler. 请注意,编译器会解析重载方法(即具有相同名称的多个方法)。 In class A , this has type A , so this.method(this) calls method(A a) . 在类Athis具有类型A ,因此this.method(this)调用method(A a) Then at runtime B 's implementation of that method is used. 然后在运行时B使用方法的实现。

Another idea is that the call this.method(this) in class A calls B.method(A a) straight out, 另一个想法是,在A类中调用this.method(this)直接调用B.method(A a),

No, it calls just method(A a) . 不,它只调用method(A a) It doesn't know anything about B . 它对B一无所知。

but that would imply that the same symbol (this) in the same context could refer to different objects. 但这意味着同一上下文中的相同符号(this)可以引用不同的对象。

It wouldn't and doesn't imply that. 它不会也不会暗示这一点。

I'll also note that public void method(){ super.method(); } 我还会注意到public void method(){ super.method(); } public void method(){ super.method(); } in B doesn't affect anything in this question. public void method(){ super.method(); }B不影响在这个问题上任何东西。

In addition to the above discussed answers, 除了上面讨论的答案,

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

Irrespective of the reference type in the first and second case, the objects are for class B . 不管第一和第二种情况下的参考类型,对象都是class B
The method() call for bb and ab invokes the super.method() block. method()调用bbab调用super.method()块。
This calls the method() from A class and passes reference of its own class to this.method(this) ie this.method(A); 这从A class调用method()并将其自己的类的引用传递给this.method(this)this.method(A);
This invokes the method method(A a) under B at run-time (method overridding). 这将在运行时调用B下的方法method(A a) (方法重写)。

In the third case, this.method(this) invokes the method method(A a) under class A. 在第三种情况下, this.method(this)调用method(A a)类下的方法method(A a)
This happens at the compile time itself (method overloading) 这发生在编译时本身(方法重载)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM