【问题标题】:Why List<Integer[]> listOfArrays = Arrays.asList(new Integer[]{1, 2}) doesn't compile? [duplicate]为什么 List<Integer[]> listOfArrays = Arrays.asList(new Integer[]{1, 2}) 无法编译? [复制]
【发布时间】:2016-07-15 13:44:31
【问题描述】:

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&lt;Integer&gt; to List&lt;Integer[]&gt;

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 &lt;T&gt; List&lt;T&gt; asList(T... a)

asList 需要 0 个或多个 T 类型的“a”。我的“a”是 new Integer[]{1, 2},它的类型是 Integer[]。那么,为什么它会生成List&lt;Integer&gt; 而不是List&lt;Integer[]&gt;

【问题讨论】:

  • 请解释 1 和 2 为何没有显示任何错误。 List 不适用于原始 int
  • @Sufian int[] 不是原始的。这是一个对象。
  • (1) 正确解析是因为T 可以是int[] 但不是int。相关stackoverflow.com/questions/2721546/…
  • OP,我建议您阅读此处标记的重复问题链中的答案,并确定它们是否完全令人满意(我不认为它们是)。如果不是,请编辑您的问题并在顶部解释您为什么认为这不是重复的。也许那样标记将被删除。

标签: java variadic-functions


【解决方案1】:

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

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

如您所见,方法签名是:

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

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

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

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

当你提供两个Integer[]s (4th)时,更明显的是编译器别无选择,只能将组成T...的两个参数视为Integer[](变成一个数组:Integer[][])。

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

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

public int iLoveMeSomeInts(int...nums)

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

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

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

更酷的是:如果您希望使用相关方法返回一个Integer[],但仍然只提供一个Integer[],您可以调用:

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

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

【讨论】:

  • 我想我真的不知道可变参数是如何工作的。
  • varvargs 很棒,因为您可以提供任意数量的相同对象,并且在方法本身中,该参数被视为一个数组。这里的问题是泛型T 必须是一个对象,因此提供int[] 不会算作ints 的可变参数。
  • 所以换句话说(如果我理解正确的话),案例 3 是模棱两可的,因为它可以被解释为两个参数 (1, 2) 和一个参数 (new Integer[]{1,2})。碰巧编译器决定选择第一个结果,如果您期待第二个结果,您会感到惊讶。
  • 关闭,但一点也不含糊。您可以为可变参数提供一个数组。我将在编辑答案时为您澄清这一点。
  • 他们可以拥有,但这有点弄巧成拙。将单个数组作为可变参数传递很方便。如果你有一个完整且准备好的Integer[],你想传递为Integer...,那么获取每个元素并将它们作为单独的参数传递会更加复杂(而且不是很直观)。相反,如果你有一个Integer[],你想作为Integer[]... 传递,你可以通过我展示的语句强制它,或者如果你不知道它,将参数传递为new Integer[][] { myIntegerArray }
猜你喜欢
  • 2015-05-29
  • 2014-01-03
  • 2017-09-13
  • 2015-09-15
  • 2011-10-21
  • 1970-01-01
  • 1970-01-01
  • 2013-05-20
  • 1970-01-01
相关资源
最近更新 更多