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