Generics, arrays, and the ClassCastException

Foo<Double> f = new Foo<Double>();

When you use this version of the generic class Foo, then for the member variable a, the compiler is essentially taking this line:

private T[] a = (T[]) new Object[5];

and replacing T with Double to get this:

private Double[] a = (Double[]) new Object[5];

You cannot cast from Object to Double, hence the ClassCastException.

Update and Clarification: Actually, after running some test code, the ClassCastException is more subtle than this. For example, this main method will work fine without any exception:

public static void main(String[] args) {
    Foo<Double> f = new Foo<Double>();
    System.out.println(f.getA());
}

The problem occurs when you attempt to assign f.getA() to a reference of type Double[]:

public static void main(String[] args) {
    Foo<Double> f = new Foo<Double>();
    Double[] a2 = f.getA(); // throws ClassCastException
    System.out.println(a2);
}

This is because the type-information about the member variable a is erased at runtime. Generics only provide type-safety at compile-time (I was somehow ignoring this in my initial post). So the problem is not

private T[] a = (T[]) new Object[5];

because at run-time this code is really

private Object[] a = new Object[5];

The problem occurs when the result of method getA(), which at runtime actually returns an Object[], is assigned to a reference of type Double[] – this statement throws the ClassCastException because Object cannot be cast to Double.

Update 2: to answer your final question “why do arrays break this?” The answer is because the language specification does not support generic array creation. See this forum post for more – in order to be backwards compatible, nothing is known about the type of T at runtime.

Leave a Comment