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
ais upcasted toSuper, the classSuperis 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 classSubis 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
doubleversion is visible, but it will get dispatched to the subclass's overridden version at runtime.