Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I create an array of a type parameter in Java?

Well, I have read a lot of answers to this question, but I have a more specific one. Take the following snippet of code as an example.

public class GenericArray<E>{
    E[] s= new E[5];
}

After type erasure, it becomes

public class GenericArray{
    Object[] s= new Object[5];
}

This snippet of code seems to work well. Why does it cause a compile-time error?

In addition, I have known from other answers that the following codes work well for the same purpose.

public class GenericArray<E>{
    E[] s= (E[])new Object[5];
}

I've read some comments saying that the piece of code above is unsafe, but why is it unsafe? Could anyone provide me with a specific example where the above piece of code causes an error?

In addition, the following code is wrong as well. But why? It seems to work well after erasure, too.

public class GenericArray<E>{
        E s= new E();
    }
like image 959
Zhu Li Avatar asked May 06 '15 11:05

Zhu Li


1 Answers

Array declarations are required to have a reifiable type, and generics are not reifiable.

From the documentation: the only type you can place on an array is one that is reifiable, that is:

  • It refers to a non-generic class or interface type declaration.

  • It is a parameterized type in which all type arguments are unbounded wildcards (§4.5.1).

  • It is a raw type (§4.8).

  • It is a primitive type (§4.2).

  • It is an array type (§10.1) whose element type is reifiable.

  • It is a nested type where, for each type T separated by a ".", T itself is reifiable.

This means that the only legal declaration for a "generic" array would be something like List<?>[] elements = new ArrayList[10];. But that's definitely not a generic array, it's an array of List of unknown type.

The main reason that Java is complaining about the you performing the cast to E[] is because it's an unchecked cast. That is, you're going from a checked type explicitly to an unchecked one; in this case, a checked generic type E to an unchecked type Object. However, this is the only way to create an array that is generic, and is generally considered safe if you have to use arrays.

In general, the advice to avoid a scenario like that is to use generic collections where and when you can.

like image 133
Makoto Avatar answered Oct 10 '22 23:10

Makoto