如果我编写Java方法
public static void f(int... x) {
for (int a: x) {
System.out.println(a);
}
}
然后我可以通过
调用此方法f(1, 2, 3);
以及
f(new int[]{1, 2, 3});
并且两个电话的处理方式完全相同。但是,这两个电话
Arrays.asList(1, 2, 3) // (a) produces a three-element Integer list
和
Arrays.asList(new int[]{1, 2, 3}) // (b) produces a one-element list of Integer arrays
不一样。 JLS状态中的The section on evaluating arguments" m 的最终形式参数必须具有某些T[]
"的类型T
。那么为什么不是最终的形式参数"如果(b)上面不是一个整数数组,它会创建一个三元素列表,如情况(a)?
我唯一能想到的是Arrays.asList
是通用的,关于类型兼容性的东西(在JLS第15.12.4.2节中提到)在这里发挥作用,但我可以&# 39;我完全把手指放在JLS中的实际句子中,使两种情况不同。
JLS中的评论讨论了为了处理参数化类型和在具有擦除泛型的Java虚拟机中发生的数组类型之间的相互作用,需要仔细制作这些语义。但我们最终得到的是我的函数f
和Arrays.asList
看起来表现不一致。在前一种情况下,我可以"解包"或"打包"我的args和一切都是一样的;在后一种情况下,两种情况不同。
这是如何用语言律师的术语解释的?
答案 0 :(得分:5)
Arrays.asList
被定义为具有参数T...
,并且正文将其视为T[]
类型的一个参数。但是,T
必须是引用类型(与任何类型参数一样),int
不是引用类型。因此,没有办法使new int[]{...}
与数组兼容以实现varargs。 (并且结果将是List<int>
,这是不允许的。)唯一的选择是将其视为单个对象,因此T
这里将是int[]
,这是一个参考类型,该函数将返回List<int[]>
。
我认为这就是原因,虽然我仍然需要查找确切的语言。它可能涉及类型推理规则,我还没有掌握。
然而,我确实试过这个:
List x = Arrays.asList(new int[]{1, 2, 3});
List y = Arrays.asList(new Integer[]{1, 2, 3});
System.out.println(x.size());
System.out.println(y.size());
(请注意,我故意使用List
原始类型,这是我在实际代码中不会做的事情。输出:
1
3
答案 1 :(得分:2)
Arrays.asList(1, 2, 3);
1 2 3被自动装箱到Integer对象,然后放在Object []
中 Arrays.asList(new int[]{1, 2, 3});
强制将3个整数转换为原始的int数组。
Arrays.asList()
预计Object[]
,因此会将您的int[]
数组放入单个元素Object[]