作者:北京城市环境监督主力军 | 来源:互联网 | 2023-05-19 07:16
我在JDK 1.8上使用IntelliJ IDEA和javac.我有以下代码:
class Test
{
@SafeVarargs
final void varargsMethod( Collection... varargs )
{
arrayMethod( varargs );
}
void arrayMethod( Collection[] args )
{
}
}
IntelliJ IDEA不会将上述代码中的任何内容突出显示为警告.但是,在编译时,"消息"视图的"生成"选项卡中会显示以下行:
警告:(L,C)java:Varargs方法可能会导致不可恢复的varargs参数varargs造成堆污染
注意#1:我已经指定了@SafeVarargs
.
注意#2:Warning:(L,C)
指向varargs
作为参数传递给arrayMethod()
假设我知道我在做什么,并且假设我非常确定不存在堆污染,或者我保证不会以某种可能导致堆污染的时髦方式调用此方法,我需要什么要压制此警告消息?
注意:有关varargs方法的stackoverflow存在大量问题,但似乎没有解决此特定问题的问题.事实上,整个interwebz对这个特定问题的答案似乎相当差.
1> 0xbe5077ed..:
我在这个问题上看到的答案似乎都不令人满意所以我认为我会抓住它.
这是我看到它的方式:
@SafeVarargs
是警告的治疗方法:[unchecked] Possible heap pollution from parameterized vararg type Foo
.
是方法契约的一部分,因此注释具有运行时保留的原因.
是方法调用者的承诺,该方法不会使用通用的varargs参数搞乱堆.
@SuppressWarnings("varargs")
是警告的治疗方法:[varargs] Varargs method could cause heap pollution from non-reifiable varargs parameter bar
.
对发生的问题治愈内的方法的代码,而不是方法的合同,因此为什么注解只有源代码保留.
告诉编译器它不需要担心方法代码调用的callee方法使用不可重新生成的varargs参数产生的数组搞乱堆.
因此,如果我对OP的原始代码采取以下简单的变化:
class Foo {
static void bar(final T... barArgs) {
baz(barArgs);
}
static 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 void bar(final T... barArgs) {
^
where T is a type-variable:
T extends Object declared in method bar(T...)
1 warning
我可以通过标记bar()
来消除警告@SafeVarargs
.这两者都会使警告消失,并且通过在方法合同中添加varargs安全性,确保调用的任何人bar
都不必禁止任何varargs警告.
但是,它也使Java编译器更仔细地查看方法代码本身 - 我想是为了验证bar()
可能违反我刚刚签订的合同的简单情况@SafeVarargs
.而且它看到bar()
所调用baz()
传递barArgs
和数据,因为baz()
需要一个Object[]
因类型擦除,baz()
会搞乱了堆,从而导致bar()
以传递地做到这一点.
所以我还需要添加@SuppressWarnings("varargs")
以便bar()
对bar()
代码的警告消失.