The following code doesn\'t compile.
package varargspkg;
public class Main {
public static void test(int... i) {
for (int t = 0; t < i.lengt
In Java, 1
is how you represent an int
. It can be either auto-boxed to an instance of Integer
or promoted to float
, and this explains why the compiler can't decide on the method it should call. But it will never be auto-boxed to Long
or Float
(or any other type).
On the other hand, if you write 1F
, it is the representation of a float
, that can be auto-boxed to a Float
(and, in the same spirit, will never be auto-boxed to an Integer
or anything else).
In Java 6, the problem lies at the time of instantiation
of your generics before finding which method is available to call.
When you write 1,2
-> it can be be both int[] or float[] and hence the issue being complained.
When you write 1,2F
-> it can be be only float[] and hence the NO issue being complained.
Same with other two option i.e.
When you write 1F,2
-> it can be be only float[] and hence the NO issue being complained.
When you write 1F,2F
-> it can be be only float[] and hence the NO issue being complained.
On the other hand, when you use int
or float
, there is no variable type instantiation. When you use 1
, it tries to find method with int
as argument first, if not, it promotes the type and identifies the method with float. If both methods available, one with the int
will be used first.
Ambiguity issue will not come in Java 7 as it has better handling of data type check and promotion.
Why is in this case the error as in the first case not reported? It appears that auto-boxing and automatic type promotion are both applied here. Is auto-boxing applied first the error is resolved?
Just an opinion - in case of varargs the JVM actually has to create an array of arguments. In case of Integer and Float, it's obvious what type of array it should create. So, it probably might be the reason for no ambiguity error.
But still, it's kind of confusing, why it can't create an array of Integers, when by default 1, 3 are ints.
Looks like this has been discussed here in SO in the past bug with varargs and overloading? and is infact a bug, according to the discussion.
You can either Widen
or Box
but you cannot do both, unless you are boxing and widening
to Object
(An int to Integer(Boxing) and then Integer to Object(Widening) is legal, since every class is a subclass of Object
, so it is possible for Integer
to be passed to Object
parameter)
Similarly an int
to Number
is also legal (int -> Integer -> Number)
Since Number is the super class of Integer
it is possible.
Let's see this in your example: -
public static void test(Integer...i)
public static void test(Float...f)
There are some rules that are followed when selecting which overloaded method to select, when Boxing, Widening, and Var-args are combined: -
smallest
method argument possibleint
can become Object
via Integer
)int
cannot become Long
)So, based on the above given rules: -
When you pass two integers to above functions,
Widened
and then
Boxed
to fit into a Long
, which is illegal according to rule 5 (You cannot Widen and then Box).Integer
var-args.But in first case, where you have methods with var-args
of primitive types: -
public static void test(int...i)
public static void test(float...f)
Then test(1, 2)
can invoke both the methods (Since neither of them is more suitable for rule 1
to apply) : -
var-args
Now, when you have methods with exactly one int and one flost: -
public static void test(int i)
public static void test(float f)
Then on invoking using test(1)
, rule 1 is followed, and smallest possible widening (i.e. the int
where no widening is needed at all) is chosen. So 1st method will be invoked.
For more information, you can refer to JLS - Method Invocation Conversion