Search code examples
javacastingoverloadingupcasting

Confusion about upcasting and overloaded methods


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:

  1. As a is upcasted to Super, the class Super is checked for a matching method
  2. Only public void f(double d) is found, so the float is casted to a double
  3. Now the method public void f(double d) in the more specific class Sub is seen and executed

Is this correct?


Solution

  • 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.