这是堆污染吗?

时间:2014-07-15 04:55:19

标签: java generics variadic-functions heap-pollution

我有一个像下面的构造函数

public MyConstructor(MyObject<T> ... objects) {
     // ...
}
Eclipse通过以下消息警告我:

  

类型安全:通过varargs参数对象潜在的堆污染

我改变了这样的构造函数:

public MyConstructor(MyObject<T>[] objects) {
     // ...
}

现在,警告消失了。但是,我认为潜在的危险并未解决。

这种解决方法有效吗?

2 个答案:

答案 0 :(得分:6)

在某种程度上,这是一种解决方法。创建不可重新组件类型的数组是不安全的。因此编译器不允许这样的数组创建表达式:

// List<String> is erased to List => disallowed
Object example = new List<String>[] { null, null };

// List<?> is effectively reifiable => allowed
Object example = new List<?>[] { null, null };

然而,允许通过变量arity方法(例如Arrays.asList)隐藏数组创建。

// RHS amounts to Arrays.asList(new List<String>[] { null, null })
List<List<String>> example = Arrays.asList(null, null);

由于您不允许创建此数组,因此您的堆不再受到污染。但是:你怎么会打电话给那个构造函数?

请注意,您的构造函数可能根本不会污染堆。它唯一的方法是

  • 它将数组转换为不太具体的类型(即MyObject<?>[]Object[])或
  • 它允许数组以某种方式转义(即将其分配给字段并从getter返回或将其传递给可能不安全的方法)。

如果你不这样做,你可以将构造函数标记为@SafeVarargs并且警告消失。

答案 1 :(得分:2)

  

但是,由于类型擦除,编译器会转换varargs   Object[]元素的形式参数。因此,有一个   堆污染的可能性。

我们知道此警告的原因主要基于类型擦除,现在它已在Java Docs中明确说明了Heap Pollution

  

如果您确保代码在没有警告的情况下编译,则不会发生堆污染。

更多关于此

  

编译器在翻译时已生成警告   varargs形式参数List<String>... l的形式参数   List[] l此声明有效;变量l的类型为List[],   这是 Object[]子类型。

那样

  

因此,如果您,编译器不会发出警告或错误   将任何类型的List对象分配给的任何数组组件   objectArray数组。

所有引用的语句都是从Java Doc

复制的