An array is a reified type. This means that the exact type of the array is known at runtime. So at runtime there is a difference between, for example, String[]
and Integer[]
.
This is not the case with generics. Generics are a compile-time construct: they are used to check the types at compile-time, but at runtime the exact types are not available anymore. At runtime, the type parameters are just Object
(or if the type parameter has an upper bound, its upper bound). So at run-time, there is no difference in the type of Collection<String>
and Collection<Integer>
.
Now, there is a problem when you want to create an array of a type parameter. At runtime it is unknown what T
is, so if you write new T[10]
, the Java runtime doesn't known what kind of array is to be created, a String[]
or a Integer[]
. That's why you cannot create an array in this way.
There are a few work-arounds, none of which is entirely satisfactory. The usual solution is to create an Object[]
, and cast it to the kind of array you want:
T[] theArray = (T[]) new Object[size];
However, you have to remember that this is very unsafe. You should only do this if the scope of the created arrow is small, so that you can manually make sure that the array will only contain T
instances and will never be assigned to anything that cannot hold it. The following code demonstrates the problem:
public class Foo<T extends Comparable> {
T[] createArray() {
return (T[])new Object[1];
}
public static void main(String... args) {
Foo<String> foo = new Foo<>();
String[] ss = foo.createArray(); // here
}
}
The line marked with here throws an exception, because you are trying to cast an Object[]
to a String[]
!
If you really need an array of the correct run-time type, you need to use reflection. Obtain a type token (of type Class<T>
) of the type you need, and use Array.newInstance(type, cize)
to create the array, for example:
public T[] createArray(Class<T> type, int size) {
return (T[]) Array.newInstance(type, size);
}