Why can't I create a generic array?
You need to know few things:
- generic types are erased at runtime, so
T
will be compiled as Object
or if <T extends SomeType>
it will become SomeType
,
to ensure safety at runtime array needs to remembers what type of elements it can hold. In other words it remembers this
new ElementType[size];
^^^^^^^^^^^
At runtime you can try to use different kind of references to hold some object. For instance if you have classes
abstract class Fruit{}
class Apple extends Fruit{}
class Banana extends Fruit{}
you can use
Fruit[] fruits = new Apple[10];
and because fruits
is treated as array of Fruit
compiler will let you write
fruits[0] = new Apple();
but also
fruits[0] = new Banana();
because fruits
can hold also Banana
arrays (for same reason it can hold now Apple
array), but as you can see Banana
is not Apple
so you need mechanism which will prevent you from corrupting your array with inappropriate elements.
So while putting element to array it performs test to check if elements type is same or subtype of class used while creating array.
This mechanism wouldn't work for
T[] f = new T[5];
because at runtime this code would look like
Object[] f = new Object[5];
which would mean that array would let you store store any kind of element which seems to be too large risk so Java creators didn't let compiler accept this kind of code.
why can I declare a reference to a generic array?
For few reasons, but mostly because there is a way to create array of T
type with little help of reflection.
If you use
T[] t = (T[])Array.newInstance(componentType, size);
you will create array of type componentType
. componentType
has to be instance of Class
which represents generic T
type. In other words our code can look like
class foo<T> {
protected T[] arr;
@SuppressWarnings("unchecked")
public foo(Class<T> componentType) {
arr = (T[]) Array.newInstance(componentType, 5);
}
}
and you can use it like
foo<String> f = new foo<String>(String.class);
// ^^^^^^^^^^^^ class literal