Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Some Java 7 warnings - how to remove them

I've finally got around to trying to get rid of all those new compiler warnings that Java 7 has kindly generated. I these two left that I cannot fathom. Is there any way of getting rid of them without suppressing them?

Constructing an array of generically typed objects (where can I put a in the array creation?):

  static final int N = 10;
//warning: [unchecked] unchecked conversion
  static final Set<Widget>[] queued = new ConcurrentSkipListSet[N];
//required: Set<Widget>[]
//found:    ConcurrentSkipListSet[]

Generic varargs (Seems to happen almost everywhere I accept varargs of a generic type):

class Foo<T> {
//warning: [unchecked] Possible heap pollution from parameterized vararg type T
  public void add(T... entries) {
//where T is a type-variable:
//T extends Object declared in class Foo

BTW: I already have:

  // Add many entries to the list.
  public void add(List<T> entries) {
    // ...
  }

  // Add a number of entries.
  public void add(T... entries) {
    // Make a list of them.
    add(Arrays.<T>asList(entries));
  }
like image 637
OldCurmudgeon Avatar asked Mar 21 '13 16:03

OldCurmudgeon


4 Answers

For the first one:

static final Set<Widget>[] queued = new ConcurrentSkipListSet<>[N];

Prior to Java 7, it would have to be:

static final Set<Widget>[] queued = new ConcurrentSkipListSet<Widget>[N];

However, you are probably better off declaring this as an ArrayList<Set<Widget>>. Generally, mixing arrays and generics is a bit difficult in Java.

static final List<Set<Widget>> queued = new ArrayList<>();
// or new ArrayList<Set<Widget>>();

Regarding the second, see this thread. Although you can suppress the message, it's actually warning about a real danger. The bottom line of that thread is that the safe thing to do is to change your method signature (and the corresponding calls) to:

class Foo<T> {
    public void add(List<T> entries) {
        . . .

The issue is basically the same as the first: you should not be creating arrays of generics.

like image 170
Ted Hopp Avatar answered Sep 28 '22 04:09

Ted Hopp


To resolve the second, you need to add @SafeVarargs to the method declaration.

From the javadocs, this is:

A programmer assertion that the body of the annotated method or constructor does not perform potentially unsafe operations on its varargs parameter. 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.

like image 45
dogbane Avatar answered Sep 28 '22 03:09

dogbane


Generic array creation:

static final ConcurrentSkipListSet<Widget>[] queued = newArray(N);
// note: declare the most specific type for private objects


@SafeVarargs
static <E> E[] newArray(int length, E... array)
{
    return Arrays.copyOf(array, length);
}

How does it work - since newArray is an vararg method, an E[] array argument must be passed in, therefore the method body has access to the type of E[]. This is theoretically correct, and if there's no erasure, it'll be totally type safe at runtime. With erasure, we only have erased type of E[] at runtime, that's fine, we return the same erased type too.

like image 41
ZhongYu Avatar answered Sep 28 '22 03:09

ZhongYu


Regarding the generic varargs warning:

  • https://stackoverflow.com/a/11195950/1172714
  • http://docs.oracle.com/javase/tutorial/java/generics/nonReifiableVarargsType.html#vulnerabilities
  • Warning for generic varargs
  • Java generics and varargs
like image 24
dsh Avatar answered Sep 28 '22 04:09

dsh