我们来看一下问题示例(3rd):
List<Integer[]> listOfArrays3 = Arrays.asList( new Integer[]{1, 2} );
正如您所展示的,方法签名是:
public static <T> List<T> asList(T... a)
在这种特殊情况下,单个Integer[]
正在考虑为T...
。可以将数组或未指定数量的同一对象提供给T...
。由于您指定了一个数组,因此T
被视为Integer
(and T...
变成Integer[]
).
当您提供一个int[]
作为单个参数(1st),编译器不会自动将其包装为Integer[]
因为这样的对象不同于int[]
。因为int
不是一个对象,唯一可以容纳的对象类型T
is int[]
(它将参数构建为int[][]
).
供应两个int[]
s (2nd)更明显,因为编译器只能将两个数组视为T...
as int[]
s, thus T...
也是int[][]
.
当您提供两个Integer[]
s (4th),再次更明显的是,编译器别无选择,只能考虑组成的两个参数T...
as Integer[]
(变成单个数组:Integer[][]
).
编辑:提供一个数组作为可变参数:
You can提供单个数组作为可变参数。让我们举一个没有泛型的例子:
public int iLoveMeSomeInts(int...nums)
供应一个int[]
将此方法作为参数确实有效。该数组被视为 varargint
s 用于验证签名的目的,则 vararg 被视为int[]
对于该方法的内部逻辑。
你的例子的不同之处在于参数是T...
。一个通用的T
must是一个对象,所以编译器不能认为int[]
作为 vararg 的int...
在这种情况下。编译器别无选择,只能考虑int[]
作为 vararg 中的单个元素int[]...
(因为int[]
是一个对象)。这一点没有任何歧义。
然而,因为Integer
is一个对象,编译器将使用单个Integer[]
as Integer...
.
更酷的是:如果你想要一个Integer[]
使用有问题的方法返回,并且仍然只提供一个Integer[]
,你可以调用:
Arrays.<Integer[]>asList(new Integer[] {1, 2});
这迫使编译器考虑你的单一Integer[]
as Integer[]...
.