Search code examples
javalanguage-design

Why can't I create an array of a generic type?


In short, this won't compile:

public <A> void test() {
    A[] temp = new A[]{};
}

Is it because of problems with backward compatibility, or is it something fundamental in the language design that prevents it?


Solution

  • The bottom line is that the class that represents the array has to know the component type. Hence the method on the Class object:

    public Class<?> getComponentType()
    Returns the Class representing the component type of an array. If this class does not represent an array class this method returns null.
    

    So when you would try:

     A[] a = new A[0];
    

    At compile time, it's obvious that we don't know the type, as it's a generic parameter. At runtime, we don't know the type due to type erasure. So instantiating the array is impossible.

    Think of the above statement as equivalent to:

     A[] a = (A[])Array.newInstance(???, 0);
    

    And due to type erasure, we can't get the class of A at runtime.

    It was asked why not have the compiler reduce to Object[] or Number[] or something like that?

    It's because a different Class will be returned depending on the component type. So:

     new Object[0].getClass() 
     new Integer[0].getClass()
    

    are not the same class. In particular the "getComponentType()" method on the class would return different values.

    So if you reduce it to Object[] instead of A[], you're not actually getting back something of type A[], you're getting back Object[]. Object[] cannot be cased to Integer[] and will yield a ClassCastException.