Choosing a Java runtime method using "super" in subclass and "this" in superclass

I discovered this seemingly strange behavior in Java technology overriding / overloading that was depressing my mind. The method call Main()

outputs " B_A " while I expect it to be " 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 like this:

  • The compiler selects a method of method()

    class B
  • At runtime, the JVM calls the method of method()

    its superclass viasuper()

  • this.method(this)

    is called from class A, but this

    refers to an instance of class B, so it translates to a method of method(B b)

    class B.
    <- this statement is not correct (thanks to Alexey Romanov and pvg). Method selection associated with overloading is always done at compile time. That is, this method translates to .m (A) before runtime. The correct override method is chosen at run time.
  • Why is method(A a)

    class B's method being called instead?

My guess is that the JVM, when it selects a subclass method at runtime, starts looking in the table of overloaded methods, where the precedence is fixed, and methods with arguments of higher classes in the hierarchy are first looked through, That is, it doesn't go straight to B.method(B b)

. instead, it scans it into a table like this, and that's ok with the first compatible method - B.method(A a)

- as B is A.

Another idea is that a call this.method(this)

in class A calls B.method(A a)

directly, but this means that the same symbol ( this

) in the same context can refer to different objects.

Any help sorting this out? Thanks in advance!

+3


source to share


2 answers


this.method (this) is called from class A, but it refers to an instance of class B, so it translates the method of method (B b) of class B.

This step is wrong. Note that overloaded methods (that is, multiple methods with the same name) are resolved by the compiler. In a class A

, this

has a type A

, so it this.method(this)

calls method(A a)

. The B

implementation of this method is then used at runtime .

Another idea is that calling this.method (this) in class A calls B.method (A a) directly,

No, it only calls method(A a)

. He knows nothing about B

.



but this means that the same symbol (this) in the same context can refer to different objects.

This does not mean and does not mean that.

Also note that public void method(){ super.method(); }

in B

no effect on this issue nothing.

+4


source


In addition to the above 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

      



Regardless of the reference type in the first and second cases, objects for class B

.
The call method()

for bb

and ab

calls the block super.method()

.
This calls method()

from A class

and passes its own class reference to this.method(this)

ie this.method(A);


This calls the method method(A a)

under B at runtime (method override).

In the third case, it this.method(this)

calls a method method(A a)

in class A.
This happens at compile time itself (method overloading)

+1


source







All Articles