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 ?
This question has already been asked a number of times. The tricky part is that
f(1, 2, 3)
is clearly passingint
's, so why can't the compiler pick thef(int...)
version? The answer must lie somewhere in the JLS, which I'm scratching my heads againstAccording to §15.12.2.4, both methods are applicable variable-arity method, so the next step is identifying the most specific one.
Unofortunately, §15.12.2.5 uses the subtype test Ti <: Si between f1(T1, .. Tn) and f2(S1, .. Sn) formal parameters to identify the target method, and since there is no subtype relationship between
Integer
andint
, no one wins, because neither int :> Integer nor Integer :> int. At the end of the paragraph is stated:Attached a blog post by Gilad Bracha (see exhibit 2), in turn linked in the bug report from the @Jayamhona's answer.
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:
Integer...
or anint...
. So far so good. And the paragraph concludes:m(a...)
is more specific than another arity methodm(b...)
. In your use case with one parameter and no generics, it boils down to:It happens that
int
is not a subtype ofInteger
andInteger
is not a subtype ofint
.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:NOTE
If you replaced
Integer...
bylong...
for example, you would haveint <: long
and the most specific method would becall(int...)
*.Similarly, if you replaced
int...
byNumber...
, thecall(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.
from JLS 15.12.2.2
neither of these methods can be passed to the other (the types for int[] and Integer[] arent related) hence the call is ambiguous
If more than one method can be applicable, than from the Java Language Specification we Choosing the Most Specific Method, paragraph
15.12.2.5
:One variable arity member method named
m
is more specific than another variable arity member method of the same name if either (<: means subtyping
):Although primitive
int
is autoboxed to wrapperInteger
,int[]
is not autoboxed toInteger[]
, than the first condition doesn't hold.Second condition is almost the same.
There are also other conditions that do not hold, and then due to JLS:
Looks like it's related to bug #6886431, which seems to be fixed in OpenJDK 7.
Below is the bug description,
Bug Description:
The compiler doesn't know which method should be called. In order to fix this, you need to cast the input parameters..
EDIT:
It is because the compiler tries to convert the Integer into int, Therefore, an implicit cast takes place prior to invocation of the
call
method. So the compiler then looks for any methods by that name that can take ints. And you have 2 of them, so the compiler doesn't know which of both should be called.