我有以下功能:
public static <T> List<T> list(T... xs) {
final List<T> lst = new ArrayList<T>();
for (final T x : xs) {
lst.add(x);
}
return lst;
}
它的用法很简单:
List<Integer> ints = list(1, 2, 3, 4)
编译器为此列表提供了以下警告
&#34; TypeSafety:via varargs参数的潜在堆污染
我试图找到它意味着什么,但我发现的所有解释都是参数的函数,这些参数本身是参数化的,例如
f(List&lt; T&gt; ... xss)。
虽然我有泛型非参数化参数的功能。
请解释一下我的功能有什么潜在的问题因为我找不到。
答案 0 :(得分:3)
Java中的Varargs是一种合成糖。 T... xs
与T[] xs
相同。因此,实际上你有一个带参数化参数(数组)的函数。
回到你的问题。当您将List<String>
作为泛型类型传递给方法时,让我们考虑一下这种情况。然后你有一个List<String>
元素数组作为你的方法的参数。由此产生了两个重要问题,并导致代码中存在可能的缺陷。
Object[] arr = xs
List
元素,遗憾的是,Java中没有办法保证放在数组中的元素正好是List<String>
。因此,如果您在运行时抛出List<Integer>
java.lang.ArrayStoreException
而不是。 这一切都会导致你可能产生堆污染的情况。请参阅以下示例:
public static <T> List<T> list(T... xs) {
final List<T> lst = new ArrayList<T>();
for (final T x : xs) {
lst.add(x);
}
Object[] arr = xs; //arrays are covariant, we can do this
arr[0] = Arrays.asList(4); //<--------heap pollution
return lst;
}
public static void main(String[] args) {
List[] arr = { Arrays.asList("one"), Arrays.asList("two"), Arrays.asList("three") };
List<List<String>> l = list(arr);
for (List list : arr) {
System.out.println(list.get(0));
}
}
输出:
4
two
three
以下是关于该主题的非常好的解释: http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ300
官方Java指南: https://docs.oracle.com/javase/8/docs/technotes/guides/language/non-reifiable-varargs.html
答案 1 :(得分:2)