如果我写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
不一样对待。 The section on evaluating arguments在 JLS 中声明“m 的最终形式参数对于某些 T
必须具有类型 T[]
”那么为什么“final”不是上面的情况 (b) 中的形式参数”不是 一个整数数组,它会创建一个三元素列表,如情况 (a)?
我唯一能想到的是 Arrays.asList
是通用的,一些关于类型兼容性(在 JLS 第 15.12.4.2 节中提到)在这里发挥作用,但我不能完全确定 JLS 中使这两种情况不同的实际句子。
JLS 中的评论谈到需要仔细设计这些语义,以处理“在具有已删除泛型的 Java 虚拟机中出现的参数化类型和数组类型”之间的相互作用,但我们最终得到的是我的函数 f
和 Arrays.asList
似乎表现不一致。在前一种情况下,我可以“解压”或“打包”我的参数,一切都是一样的;在后一种情况下,这两种情况是不同的。
这在语言律师术语中是如何解释的?
最佳答案
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
关于java - 如何解释这种看似不一致的 Java 可变参数行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27142662/