@SafeVarargs vs @SuppressWarnings("varargs")
Anthony Vanelverdinghe
dev at anthonyv.be
Fri May 1 17:39:06 UTC 2020
Hi
Please consider the following class:
import java.util.*;
import java.util.function.Predicate;
class Foo {
@SafeVarargs // suppresses (1) but not (2)
@SuppressWarnings("varargs") // suppresses (2) but not (1)
static <T> void bar(T o, Predicate<T>... predicates) {
// (1) warning: [unchecked] Possible heap pollution from
parameterized vararg type Predicate<T>
for(Predicate<T> predicate : predicates) {
predicate.test(o);
}
// (2) warning: [varargs] Varargs method could cause heap
pollution from non-reifiable varargs parameter predicates
Arrays.stream(predicates).forEachOrdered(predicate ->
predicate.test(o));
}
// copied from
https://docs.oracle.com/en/java/javase/14/docs/specs/man/javac.html#examples-of-using--xlint-keys
public static <T> void addToList(List<T> listArg, T... elements) {
for (T x : elements) {
listArg.add(x);
}
}
static void baz() {
addToList(List.of(""), "foo");
}
}
As you can see, the method `bar` does the same thing twice, but in
different ways: the first time it uses an enhanced for statement, the
second time it uses Arrays::stream.
Using a for-loop results in a warning of type "unchecked", which can be
suppressed with @SafeVarargs.
Using Arrays::stream results in a warning of type "varargs", which can
be suppressed with @SuppressWarnings("varargs").
The method `addToList` was copied from the documentation for the
"varargs" Xlint type [1], which states that its compilation will create
the warning: "warning: [varargs] Possible heap pollution from
parameterized vararg type T".
However, comparing with the `bar` method, this is the Xlint type of the
second warning, combined with the message of the first warning, which
seems suspicious. And indeed, compiling it gives me an "unchecked"
warning, not a "varargs" warning.
Moreover, the documentation first says: "Warns about unsafe **use** of
variable arguments (varargs) methods", but then after the example says:
"The compiler generates the following warning for the **definition** of
the method".
From the documentation I thought that the "varargs" type is indeed
about uses of varargs methods which haven't been annotated with
`@SafeVarargs`. But this is contradicted by the invocation of
`addToList` in the method `baz`, which doesn't result in an Xlint
warning at all.
To summarize, I believe:
* there are 2 issues with javac here:
1) both warnings in the `bar` method should be the same, namely:
"warning: [unchecked] Possible heap pollution from parameterized vararg
type Predicate<T>" and only `@SafeVarargs` should be needed to be able
to compile the method without any warnings
2) there's no warning in `baz`, even though I think it should give
a warning of type "varargs"
* and the current documentation for the "varargs" Xlint type is wrong
Is the above correct? If so, I'll file bug reports for these. If not,
I'm confused, so I'd appreciate any clarifications.
Kind regards,
Anthony
[1]
https://docs.oracle.com/en/java/javase/14/docs/specs/man/javac.html#examples-of-using--xlint-keys
More information about the compiler-dev
mailing list