【问题标题】:Is this a heap pollution work around?这是一个堆污染​​工作吗?
【发布时间】:2014-09-05 04:04:37
【问题描述】:

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

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

Eclipse 用以下消息警告我:

类型安全:可变参数对象造成的潜在堆污染

我这样改变构造函数:

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

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

这种解决方法有效吗?

【问题讨论】:

  • MyObject&lt;T&gt; ... objectsMyObject&lt;T&gt;[] objects 行为相似,但它们不一样...

标签: java generics variadic-functions heap-pollution


【解决方案1】:

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

// 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 };

但是,允许通过可变参数方法(例如 Arrays.asList)创建隐藏数组。

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

由于您不允许创建此数组,因此您的堆不会再受到污染。但是:您将如何调用该构造函数?

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

  • 它将数组转换为不太具体的类型(即MyObject&lt;?&gt;[]Object[])或
  • 它让数组以某种方式逃逸(即将它分配给一个字段并从一个 getter 返回或将它传递给一个可能不安全的方法)。

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

【讨论】:

    【解决方案2】:

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

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

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

    还有更多内容

    编译器在翻译 varargs 形参List&lt;String&gt;... l 到形参 List[] l此声明有效;变量 l 的类型为List[], 这是Object[]子类型

    这样

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

    所有引用的语句都是从 Java Doc 复制而来的

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-24
      • 1970-01-01
      • 2013-08-22
      • 1970-01-01
      • 1970-01-01
      • 2013-11-09
      • 1970-01-01
      相关资源
      最近更新 更多