Case 1
static void call(Integer i) {
System.out.println("hi" + i);
}
static void call(int i) {
System.out.println("hello" + i);
}
public static void main(String... args) {
call(10);
}
Output of Case 1 : hello10
Case 2
static void call(Integer... i) {
System.out.println("hi" + i);
}
static void call(int... i) {
System.out.println("hello" + i);
}
public static void main(String... args) {
call(10);
}
Shows compilation error reference to call ambiguous
. But, I was unable to understand. Why ? But, when I commented out any of the call()
methods from Case 2
, then It works fine. Can anyone help me to understand, what is happening here ?
Finding the most specific method is defined in a very formal way in the Java Language Specificaion (JLS). I have extracted below the main items that apply while trying to remove the formal formulae as much as possible.
In summary the main items that apply to your questions are:
The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing, and unboxing.
Integer...
or an int...
. So far so good. And the paragraph concludes:The most specific method (§15.12.2.5) is chosen among the applicable variable-arity methods.
m(a...)
is more specific than another arity method m(b...)
. In your use case with one parameter and no generics, it boils down to:
m(a...)
is more specific thanm(b...)
iifa <: b
, where<:
meansis a subtype of
.
It happens that int
is not a subtype of Integer
and Integer
is not a subtype of int
.
To use the JLS language, both call
methods are therefore maximally specific (no method is more specific than the other). In this case, the same paragraph concludes:
- If all the maximally specific methods have override-equivalent (§8.4.2) signatures [...] => not your case as no generics are involved and Integer and int are different parameters
- Otherwise, we say that the method invocation is ambiguous, and a compile-time error occurs.
NOTE
If you replaced Integer...
by long...
for example, you would have int <: long
and the most specific method would be call(int...)
*.
Similarly, if you replaced int...
by Number...
, the call(Integer...)
method would be the most specific.
*There was actually a bug in JDKs prior to Java 7 that would show an ambiguous call in that situation.