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));
}
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.
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.
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.
Regarding the generic varargs warning:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With