为什么@SafeVarargs不会禁止警告?

时间:2017-06-21 11:59:23

标签: java

以下是代码:

class Foo<T> {
  private final T[] array;
  @SafeVarargs
  Foo(T... items) {
    this.array = items;
  }
}

我得到了:

[WARNING] Varargs method could cause heap pollution 
from non-reifiable varargs parameter items

我的任务有什么问题?如何解决? @SuppressWarnings不是一个选项,因为我希望这个构造函数真正安全。&#34;

$ javac -version
javac 1.8.0_40

3 个答案:

答案 0 :(得分:2)

Joshua Bloch在Effective Java(25章)中解释了这一点:

  

禁止通用阵列创建可能很烦人。它的意思是,   例如,泛型类型通常不可能   返回其元素类型的数组(但参见第29项的部分   解)。这也意味着你可以在什么时候收到令人困惑的警告   使用varargs方法(第42项)与泛型类型相结合。   这是因为每次调用varargs方法时,都会有一个数组   创建用于保存varargs参数。如果元素类型为此   数组不可恢复,您会收到警告。你几乎无能为力   关于这些警告,除了压制它们(第24项),以及   避免在API中混合泛型和变种。

spec中描述了此消息的原因,在this部分规范中,有类似示例(使用类ArrayBuilder和注释用法的不同组合)

与替代方案一样,尝试使用SafeVarargs和SuppressWarnings注释的混合

@SafeVarargs
@SuppressWarnings( "varargs" )

HTH

答案 1 :(得分:1)

来自docs

  

将此批注应用于方法或构造函数可以抑制有关不可重新生成的变量arity(vararg)类型 的未经检查的警告,并且可以抑制有关参数化数组创建的未经检查的警告在呼叫网站

第一个语句告诉我们@SafeVarargs抑制未经检查的警告:

  • varargs的不可重复类型
  • 调用方法时参数化的数组创建

在您的情况下,@SafeVarargs正在取消T... items上的警告。您的警告发生在this.array = items;

来自JLS §9.6.4.7

  

注释@SafeVarargs具有非本地效果,因为除了未选中之外,还禁止在方法调用表达式中禁止未经检查的警告警告与变量arity方法本身的声明有关

           

相反,注释@SuppressWarnings("unchecked")具有局部效果,因为它仅抑制与方法声明有关的未经检查的警告。

答案 2 :(得分:1)

我的问题是我使用-Xlint命令行javac参数。我发现我必须使用以下参数编译它:

javac -Werror -Xlint -Xlint:-varargs

那就是它。