Reputation:
Given the following source and ouput:
Source:
public class A
{
public void foo()
{
bar();
}
public void bar()
{
System.out.println ("in A's bar() method");
}
}
public class B extends A
{
@Override
public void foo()
{
super.foo();
// Do some specialized B stuff
}
@Override
public void bar()
{
System.out.println ("in B's bar() method");
}
}
public class Main
{
public static void main (String... args)
{
B b = new B();
b.foo();
}
}
Output:
in B's bar() method
Can someone please explain to me how the JVM is smart enough to polymorphically call B's (as opposed to A's) bar() method in this situation? I'd like to know what kind of dynamic dispatch magic is going on behind the scenes here.
Update: In case I wasn't clear enough, I know basically WHAT is happening, I'm looking for specific details on HOW the JVM makes it happen under the hood. The answers so far are too simplistic.
Update 2: Maybe I wasn't clear enough. When b.foo()
is called, then super.foo()
is called, then bar()
is called in class A's foo()
. How does the bar()
that is called when specifically invoking super.foo()
not call class A's bar()
method, since the super
keyword explicitly specifies class A? What steps does the JVM have to go through to sort this out?
Also, does this mean it's a bad idea in general to call public methods from within their own class since they can be overridden in this way?
Upvotes: 3
Views: 678
Reputation: 20470
The function call sequence is (from eclipse debug view):
1. B.foo() // super.foo()
2. B(A).foo() // bar()
3. B.bar()
After the thread calls super.foo(), the JVM will check if there's any implementation in B (since we still hold B.class in the stack), if there is, JVM will call it.
This feature is guaranteed by JVM implementation. It is not smart, it just be designed this way, just like C++'s virtual methods.
Hope it helps.
Upvotes: 1
Reputation: 4878
Even if the constructor or method you're currently in is defined in a super-class, the object doesn't change type. It will still be an object of type B
. This can be demonstrated by using the this
keyword.
this
refers to the current object. That is not the same as the class defining the current method or constructor.
Try typing the following into A
's constructor or in the foo()
method:
System.out.println(this.getClass());
Upvotes: 1
Reputation: 310
Java uses the object's type when invoking the methods.
A b = new B();
b.foo();
Let's say you used above code. Here what will happen is you are creating an object of type B and assign it to a reference of type A. Since the object type is B, you'll invoke the method in class B.
Upvotes: 3