In this case, it is perfectly okay to suppress the unchecked cast warning.
It's an unchecked cast because E
is not known at runtime. So the runtime check can only check the cast up to Object[]
(the erasure of E[]
), but not actually up to E[]
itself. (So for example, if E
were Integer
, then if the object's actual runtime class was String[]
, it would not be caught by the check even though it's not Integer[]
.)
Array.newInstance()
returns Object
, and not E[]
(where E
would be the type argument of the Class
parameter), because it can be used to create both arrays of primitives and arrays of references. Type variables like E
cannot represent primitive types, and the only supertype of array-of-primitive types is Object
. Class
objects representing primitive types are Class
parameterized with its wrapper class as the type parameter, e.g. int.class
has type Class<Integer>
. But if you pass int.class
to Array.newInstance()
, you will create an int[]
, not E[]
(which would be Integer[]
). But if you pass a Class<E>
representing a reference type, Array.newInstance()
will return an E[]
.
So basically, calling Array.newInstance()
with a Class<E>
will always return either an E[]
, or an array of primitives. An array-of-primitives type is not a subtype of Object[]
, so it would fail a runtime check for Object[]
. In other words, if the result is an Object[]
, it is guaranteed to be an E[]
. So even though this cast only checks up to Object[]
at runtime, and it doesn't check the part from Object[]
up to E[]
, in this case, the check up to Object[]
is sufficient to guarantee that it is an E[]
, and so the unchecked part is not an issue in this case, and it is effectively a fully checked cast.
By the way, from the code you have shown, you do not need to pass a class object to initialize GenSet
or to use Array.newInstance()
. That would only be necessary if your class actually used the class E
at runtime. But it doesn't. All it does is create an array (that is not exposed to the outside of the class), and get elements from it. That can be achieved using an Object[]
. You just need to cast to E
when you take an element out (which is unchecked by which we know to be safe if we only put E
s into it):
public class GenSet<E> {
private Object[] a;
public GenSet(int s) {
this.a = new Object[s];
}
@SuppressWarnings("unchecked")
E get(int i) {
return (E)a[i];
}
}