我正在阅读有关varargs heap pollution的信息,但我并没有真正理解varargs或非可整流类型将如何处理没有通用性就不存在的问题。确实,我可以很容易地替换

public static void faultyMethod(List<String>... l) {
    Object[] objectArray = l; // Valid
    objectArray[0] = Arrays.asList(42);
    String s = l[0].get(0); // ClassCastException thrown here
}


public static void faultyMethod(String... l) {
    Object[] objectArray = l; // Valid
    objectArray[0] = 42;  // ArrayStoreException thrown here
    String s = l[0];
}

第二个简单地使用数组的协方差,这确实是这里的问题。 (即使List<String>是可修复的,我想它仍然是Object的子类,并且我仍然可以将任何对象分配给数组。)当然,我可以看到两者之间有一些区别,但是此代码是错误的是否使用泛型。

它们所谓的堆污染是什么意思(它使我想到了内存使用情况,但他们谈论的唯一问题是潜在的类型不安全性),它与使用数组协方差的任何类型违例有何不同?

最佳答案

没错,常见(基本)问题是数组的协方差。但是,在您给出的两个示例中,第一个更危险,因为可以修改数据结构并将其置于可能会在以后破坏的状态。

考虑一下您的第一个示例是否未触发ClassCastException:

public static void faultyMethod(List<String>... l) {
  Object[] objectArray = l;           // Valid
  objectArray[0] = Arrays.asList(42); // Also valid
}

这是某人使用它的方式:
List<String> firstList = Arrays.asList("hello", "world");
List<String> secondList = Arrays.asList("hello", "dolly");
faultyMethod(firstList, secondList);
return secondList.isEmpty()
  ? firstList
  : secondList;

因此,现在我们有了一个List<String>,实际上包含一个Integer,它安全地在周围 float 。稍后,可能要晚得多,如果要序列化,可能要晚得多,并且在另一个JVM中,某个人最终将执行String s = theList.get(0)。此故障与导致故障的原因相距甚远,因此很难追踪。

请注意,ClassCastException的堆栈跟踪不会告诉我们错误的真正发生位置。它只是告诉我们是谁触发了它。换句话说,它并没有为我们提供有关如何修复该错误的大量信息。这就是它比ArrayStoreException大得多的原因。

关于java - varargs堆污染: what's the big deal?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32291515/

10-10 01:09