Search code examples
javaoverloadingcompile-time

how does Java's most specific method rule for overloaded methods work with multiple parameters?


Consider the following code:

class Driver {
    public static void main(String[] args) {
        Test1 t1 = new Test1();
        Test2 t2 = new Test2();
        Test3 t3 = new Test3();
        
        Object o = "";
        String s = "";
        
        t2.method1(t2, o); // calls method1 on Test1
        t2.method1(t3, s); // compile error: reference to method1 is ambiguous
    }
}

class Test1 {
    public void method1(Test2 v1, Object o) {
        System.out.println("Test1 called");
    }
}

class Test2 extends Test1 {
    public void method1(Test1 v1, String o) {
        System.out.println("Test2 called");
    }
}

class Test3 extends Test2 {
}

I essentially have a Test1 class which has subclass Test2 which has subclass Test3.
I just learned that to deal with overloaded methods which have arguments that are related to each other through some is-a relationship, java picks the most specific method.
I wanted to test how this worked when there are multiple parameters.

The first call resolves to Test1's implementation, which makes sense: Object is not a String, so method1(Test1 v1, String o) in Test2 isn't a match.

But for the second call, shouldn't the t2.method1(t3, s) just resolve to method1(Test2 v1, Object o), as that is the most "specific": Test3 is 1 class away from Test2 and String is 1 class away from Object?

Instead the the compiler returns reference to method1 is ambiguous.

How does Java deal with such cases?


Solution

  • The actual call is

     method1(Test3, String)
    

    The applicable methods, on a Test2 object reference, are

     method1(Test1, String)   // A
     method1(Test2, Object)   // B
    

    For the first argument, type Test2, B is preferred - Test2 is more specific than Test1.

    For the second argument, type String, A is preferred - String is more specific than Object.

    Thus neither A or B is unambiguously selected. Resolution requires a target method that is the most specific for every actual argument.

    Java Language Supplement