为什么 List<Integer[]> listOfArrays = Arrays.asList(new Integer[]{1, 2}) 不编译?

Why List<Integer[]> listOfArrays = Arrays.asList(new Integer[]{1, 2}) doesn't compile?

1) 好的

List<int[]> listOfArrays1 = Arrays.asList( new int[]{1, 2} );

2) 好的

List<int[]> listOfArrays2 = Arrays.asList( new int[]{1, 2}, new int[]{3, 4} );

3) 编译错误Type mismatch: cannot convert from List<Integer> to List<Integer[]>

List<Integer[]> listOfArrays3 = Arrays.asList( new Integer[]{1, 2} );

4) 好的

List<Integer[]> listOfArrays4 = Arrays.asList( new Integer[]{1, 2},  new Integer[]{3, 4} );

这是 asList 的签名:public static <T> List<T> asList(T... a)

asList 需要 0 个或多个 "a" 类型的 T。我的 "a" 是 new Integer[]{1, 2} 并且它是 Integer[] 类型。那么,为什么它生成 List<Integer> 而不是 List<Integer[]>

我们来看问题示例(3rd):

List<Integer[]> listOfArrays3 = Arrays.asList( new Integer[]{1, 2} );

如您所示,方法签名是:

public static <T> List<T> asList(T... a)

在这种特殊情况下,T... 正在考虑单个 Integer[]。可以向 T... 提供数组或未指定数量的相同对象。由于您指定了一个数组,因此 T 被视为 Integer(并且 T... 变为 Integer[])。

当您提供 int[] 作为单个参数 (1st) 时,编译器不会自动将其包装为 Integer[],因为这样对象不同于 int[]。因为 int 不是对象,所以唯一可以适合 T 的对象类型是 int[](它将参数构建为 int[][])。

提供两个 int[]s (2nd) 更明显,因为编译器只能将 T... 的两个数组视为 int[]s,因此 T... 也是 int[][].

当您提供两个 Integer[]s (4th) 时,编译器别无选择,只能考虑构成 T... as Integer[](变成一个数组:Integer[][])。

编辑:提供数组作为可变参数:

可以提供单个数组作为可变参数。让我们举一个没有泛型的例子:

public int iLoveMeSomeInts(int...nums)

向此方法提供 int[] 作为参数确实有效。出于验证签名的目的,该数组被视为 int 的可变参数,然后该可变参数被视为方法内部逻辑的 int[]

您示例中的不同之处在于参数是 T...。泛型 T 必须 是一个对象,因此在这种情况下编译器不能将 int[] 视为 int... 的可变参数。然后编译器别无选择,只能将 int[] 视为 int[]... 的可变参数中的单个元素(因为 int[] 是一个对象)。这一点没有歧义。

但是,因为 Integer 一个对象,编译器将使用单个 Integer[] 作为 Integer...

更酷的是:如果你想使用有问题的方法返回一个 Integer[],但仍然只提供一个 Integer[],你可以调用:

Arrays.<Integer[]>asList(new Integer[] {1, 2});

这会强制编译器将您的单个 Integer[] 视为 Integer[]...