1) OK
List<int[]> listOfArrays1 = Arrays.asList( new int[]{1, 2} );
2) OK
List<int[]> listOfArrays2 = Arrays.asList( new int[]{1, 2}, new int[]{3, 4} );
3) Compile error Type mismatch: cannot convert from List<Integer> to List<Integer[]>
List<Integer[]> listOfArrays3 = Arrays.asList( new Integer[]{1, 2} );
4) OK
List<Integer[]> listOfArrays4 = Arrays.asList( new Integer[]{1, 2}, new Integer[]{3, 4} );
This is the signature for asList
: public static <T> List<T> asList(T... a)
asList
expects 0 or more "a" of type T. My "a" is new Integer[]{1, 2}
and it is of type Integer[]
. So, why is it generating a List<Integer>
instead of a List<Integer[]>
?
Let's look at the problem example (3rd):
List<Integer[]> listOfArrays3 = Arrays.asList( new Integer[]{1, 2} );
As you showed, the method signature is:
public static <T> List<T> asList(T... a)
In this particular case, the single Integer[]
is being considered for the T...
. An array or an unspecified number of the same object can be supplied to T...
. Since you specified one array, the T
is regarded as Integer
(and T...
becomes Integer[]
).
When you supply an int[]
as a single argument (1st), the compiler doesn't automatically wrap this to an Integer[]
because such an object is different from an int[]
. Because int
is not an object, the only object type that can fit T
is int[]
(which builds the parameter as an int[][]
).
Supplying two int[]
s (2nd) is much more obvious, as the compiler can only regard two arrays for T...
as int[]
s, thus T...
is also int[][]
.
When you supply two Integer[]
s (4th), it is more obvious again that the compiler has no choice but to regard the two parameters which make up T...
as Integer[]
(which becomes a single array: Integer[][]
).
Edit: Supplying an array as a vararg:
You can supply a single array as a vararg. Let's take an example without a generic:
public int iLoveMeSomeInts(int...nums)
Supplying an int[]
to this method as an argument does work. The array is regarded as a vararg of int
s for the purposes of validating the signature, then the vararg is regarded as an int[]
for the method's internal logic.
The difference in your example is that the argument is T...
. A generic T
must be an object, so the compiler cannot regard an int[]
as a vararg of int...
in this case. The compiler then has no choice but to regard the int[]
as a single element in a vararg of int[]...
(because int[]
is an object). There is no ambiguity in this.
However, because Integer
is an object, the compiler will use a single Integer[]
as Integer...
.
What's even cooler is this: if you wanted an Integer[]
returned using the method in question, and still only supplied a single Integer[]
, you could call:
Arrays.<Integer[]>asList(new Integer[] {1, 2});
This forces the compiler to regard your single Integer[]
as Integer[]...
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With