java - 可变参数堆污染 : what's the big deal?

标签 java generics memory variadic-functions heap-pollution

我正在阅读 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 ,它安全地漂浮着。在稍后的某个时刻——可能更晚,如果它被序列化,可能很多更晚并且在不同的 JVM 中——终于有人执行 String s = theList.get(0) .此故障与导致它的原因相距甚远,因此可能很难追查。

请注意,ClassCastException 的堆栈跟踪并没有告诉我们错误真正发生在哪里;它只是告诉我们是谁触发了它。换句话说,它并没有为我们提供太多关于如何修复错误的信息。这就是它比 ArrayStoreException 更重要的原因。

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

相关文章:

java - 从构造函数中抛出未处理的异常时会发生什么

java - 如何在没有 xml 的情况下配置 Ehcache 3 + spring boot + java config?

Swift 嵌套泛型类型不符合协议(protocol)

无法从具有多个返回的 Select 中的用法推断出 C# 类型参数

java - 从注解引用参数化类型

java.util.Date 和 UTC 问题

java - 清除期间 couchdb gen_server 调用超时

swift - swift 中带有选项的结构的大小

c++ - 带有编译时数组的自定义分配器

algorithm - 依赖评估的 DAG 的最佳内存跟踪