我正在阅读有关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/