Let's say, we have these two classes and one main method:
public class Super {
public void f(double d){
System.out.println("Super: f(double d)");
}
public void f(int i){
System.out.println("Super: f(int i)");
}
}
public class Sub extends Super {
public void f(double d){
System.out.println("Sub: f(double d)");
}
public void f(float f){
System.out.println("Sub: f(float f)");
}
}
public class M {
public static void main(String[] args){
Sub a = new Sub();
a.f(1.5f); //output: "Sub: f(float f)"
Super b = new Sub();
b.f(1.5f); //output: "Sub: f(double d)"
}
}
Why does the second call results in Sub: f(double d)
and not in Sub: f(float f)
like the first one?
When I add
public void f(float f) {
System.out.println("Super: f(float f)");
}
to the Super
class, the output changes to Sub: f(float f)
.
Given this behavior, I expect the workflow looks like this:
- As
a
is upcasted toSuper
, the classSuper
is checked for a matching method - Only
public void f(double d)
is found, so the float is casted to a double - Now the method
public void f(double d)
in the more specific classSub
is seen and executed
Is this correct?
To understand this behavior, note that choosing which method to call out of a series of overloaded methods is always performed at compile-time. However, method dispatch is performed at runtime.
Therefore, at compile-time, only the
double
version is visible, but it will get dispatched to the subclass's overridden version at runtime.