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 ints 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