Java警告:Varargs方法可能会导致来自不可修改的varargs参数的堆污染

迈克·纳基斯(Mike Nakis):

我在JDK 1.8上将IntelliJ IDEA与javac一起使用。我有以下代码:

class Test<T extends Throwable>
{
    @SafeVarargs
    final void varargsMethod( Collection<T>... varargs )
    {
        arrayMethod( varargs );
    }

    void arrayMethod( Collection<T>[] args )
    {
    }
}

IntelliJ IDEA不会在上面的代码中突出显示任何内容作为警告。但是,在编译时,以下行将显示在“消息”视图的“生成”选项卡中:

警告:(L,C)java:Varargs方法可能会导致不可修改的varargs参数varargs造成堆污染

注意#1:我已经指定了@SafeVarargs

注意#2:Warning:(L,C)指向varargs作为参数传递给arrayMethod()

假设我知道自己在做什么,并且假设我非常确定不会出现堆污染,或者我保证不会以某种时髦的方式调用此方法,这可能会导致堆污染,那么我需要做些什么?禁止显示此警告消息?

注意:关于varargs方法,关于stackoverflow有很多问题,但似乎没有一个问题可以解决此特定问题。实际上,整个interwebz在回答这个特定问题方面似乎很差。

0xbe5077ed:

在这个问题上,我所看到的答案都没有一个令人满意,因此我认为我会采取行动。

这是我的看法:

  1. @SafeVarargs

    • 是解决警告的方法:[unchecked] Possible heap pollution from parameterized vararg type Foo
    • 是方法约定的一部分,因此注释为何具有运行时保留
    • 向方法的调用者保证,该方法不会使用泛型varargs参数弄乱堆。
  2. @SuppressWarnings("varargs")

    • 是解决警告的方法:[varargs] Varargs method could cause heap pollution from non-reifiable varargs parameter bar
    • 解决方法代码发生的问题,而不是方法合同上的问题,因此注释为何仅保留源代码
    • 告诉编译器不必担心方法代码调用的被调用方方法会使用由不可修改的varargs参数产生的数组将堆弄乱。

因此,如果我对OP的原始代码进行以下简单修改:

class Foo {
    static <T> void bar(final T... barArgs) {
        baz(barArgs);
    }
    static <T> void baz(final T[] bazArgs) { }
}

$ javac -Xlint:all Foo.java使用Java 9.0.1编译器的输出为:

Foo.java:2: warning: [unchecked] Possible heap pollution from parameterized vararg type T
    static <T> void bar(final T... barArgs) {
                                   ^
  where T is a type-variable:
    T extends Object declared in method <T>bar(T...)
1 warning

我可以通过将标记bar()为来消除该警告@SafeVarargs这既使得警告消失,并通过增加可变参数安全的方法合同,确保任何人谁通话bar将不必抑制任何可变参数的警告。

但是,这也使Java编译器更加仔细地查看了方法代码本身-我想是为了验证一些简单的情况,这些情况bar()可能会违反我刚刚订立的合同@SafeVarargs而且它看到bar()所调用baz()传递barArgs和数据,因为baz()需要一个Object[]因类型擦除,baz()会搞乱了堆,从而导致bar()以传递地做到这一点。

因此,我还需要添加@SuppressWarnings("varargs")bar()以使有关bar()的代码的警告消失。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

IntelliJ警告:varargs参数的未经检查的泛型数组创建

Enum <E>的“通过varargs参数潜在的堆污染” ...为什么?

如何使用varargs方法中的附加参数调用varargs方法

在Java中强制用户填充varargs参数的好方法

varargs堆污染:有什么大不了的?

使用变量参数重载方法(varargs)

varargs和'...'参数

是否有可能解决“为varargs参数创建T的通用数组”的编译器警告?

我得到了这样的警告:varargs方法的non-varargs调用,其中最后一个参数的参数类型不精确;

用单个null参数调用Java varargs方法?

通过varargs参数可能导致堆污染

Java多参数点表示法-Varargs

Java varargs方法参数列表与数组

Java堆污染

Java Vaadin组合框警告Intellij:不清楚是否需要varargs或non-varargs调用

[Vue警告]:检测到重复的密钥:x。这可能会导致更新错误

Java方法重载和varargs

防止“ PerformSelect的选择器未知,可能会导致泄漏”的警告

方法调用可能会产生java NullpointerException

从Kotlin调用Java varargs方法

无法修复警告检测到重复键:“ 0”。这可能会导致更新错误

[Vue警告]:检测到重复的密钥:x。这可能会导致更新错误。如何防止添加已通过方法添加的项目

为什么不可能指定Scala varargs参数的默认值?

关于varargs参数的困惑

方法参数作为List的varargs

警告:移动分区可能会导致操作系统无法启动

类型安全性:通过varargs参数子树的潜在堆污染

警告:方法调用 getAssets 可能会产生 nullpointerexception

Varargs 污染堆