Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why @SafeVarargs doesn't suppress the warning?

Tags:

java

Here is the code:

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

I'm getting:

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

What's wrong with my assignment? How to fix that? @SuppressWarnings is not an option, since I want this constructor to be truly "safe."

$ javac -version
javac 1.8.0_40
like image 776
yegor256 Avatar asked Jun 21 '17 11:06

yegor256


2 Answers

From the docs:

Applying this annotation to a method or constructor suppresses unchecked warnings about a non-reifiable variable arity (vararg) type and suppresses unchecked warnings about parameterized array creation at call sites.

The first statement tells us @SafeVarargs suppresses unchecked warnings about:

  • non-reifiable type for your varargs
  • parameterized array creations when you call the method

In your case, @SafeVarargs is suppressing the warning on T... items. Your warning is occuring on this.array = items;.


From the JLS §9.6.4.7:

The annotation @SafeVarargs has non-local effects because it suppresses unchecked warnings at method invocation expressions in addition to an unchecked warning pertaining to the declaration of the variable arity method itself.


In contrast, the annotation @SuppressWarnings("unchecked") has local effects because it only suppresses unchecked warnings pertaining to the declaration of a method.

like image 147
Vince Avatar answered Nov 15 '22 22:11

Vince


Joshua Bloch explains this in Effective Java (25s chapter):

The prohibition on generic array creation can be annoying. It means, for example, that it’s not generally possible for a generic type to return an array of its element type (but see Item 29 for a partial solution). It also means that you can get confusing warnings when using varargs methods (Item 42) in combination with generic types. This is because every time you invoke a varargs method, an array is created to hold the varargs parameters. If the element type of this array is not reifiable, you get a warning. There is little you can do about these warnings other than to suppress them (Item 24), and to avoid mixing generics and varargs in your APIs.

The reason for this message is described in spec, in this part of spec, there is similar example (with class ArrayBuilder and different combinations of annotation usage)

Like alternative, try to use mix of SafeVarargs and SuppressWarnings annotations

@SafeVarargs
@SuppressWarnings( "varargs" )

HTH

like image 1
Artem Avatar answered Nov 15 '22 23:11

Artem