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:
a
is upcasted to Super
, the class Super
is checked for a matching methodpublic void f(double d)
is found, so the float is casted to a doublepublic void f(double d)
in the more specific class Sub
is seen and executedIs 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.