10

Can someone please explain what is meant by the following statement :

Creation of arrays with a non-reifiable component type is not permitted.

This is written in Anjelika Langer's Java Generics FAQ

Geek
  • 23,609
  • 39
  • 133
  • 212

3 Answers3

9

Creation of arrays with a non-reifiable component type is not permitted.

in practice means that generic array creation is illegal:

new T[...] // prohibited

Generic arrays are not allowed, because arrays contain information about its component at runtime. This is not true for generics. Generics are implemented at compiler level. Hence, the component type must be known beforehand when the array is created.

Konrad Reiche
  • 25,626
  • 13
  • 100
  • 139
  • can you also explain why it is not permitted in your answer ? That would just make it more complete . – Geek Oct 09 '12 at 13:25
  • I have added an explanation which makes it clear for me. For a more in-depth discussion the answers to the question [What's the reason I can't create generic array types in Java?](http://stackoverflow.com/questions/2927391/whats-the-reason-i-cant-create-generic-array-types-in-java) are useful. – Konrad Reiche Oct 09 '12 at 13:51
4

Java programming language does not permit the creation of arrays of parameterized types i.e. new T [] is not permitted

If the element type of an array were not reifiable (§4.7), the virtual machine could not perform the store check described in the preceding paragraph. This is why creation of arrays of non-reifiable types is forbidden. One may declare variables of array types whose element type is not reifiable, but any attempt to assign them a value will give rise to an unchecked warning (§5.1.9).

You can read more about it here See more:

Below is the code example which displays what can go wrong if you use varargs with generic types.

public class ArrayBuilder {

public static <T> void addToList(List<T> listArg, T... elements) {
    for (T x : elements) {
        listArg.add(x);
    }
}

public static void faultyMethod(List<String>... l) {
    Object[] objectArray = l; // Valid
    objectArray[0] = Arrays.asList(42);
    String s = l[0].get(0); // ClassCastException thrown here
}

public static void main(String[] args) {

    List<String> stringListA = new ArrayList<String>();
    List<String> stringListB = new ArrayList<String>();

    ArrayBuilder.addToList(stringListA, "Seven", "Eight", "Nine");
    ArrayBuilder.addToList(stringListA, "Ten", "Eleven", "Twelve");
    List<List<String>> listOfStringLists = new ArrayList<List<String>>();
    ArrayBuilder.addToList(listOfStringLists, stringListA, stringListB);

    ArrayBuilder.faultyMethod(Arrays.asList("Hello!"),
            Arrays.asList("World!"));
}

}

When the compiler encounters a varargs method, it translates the varargs formal parameter into an array. However, the Java programming language does not permit the creation of arrays of parameterized types. In the method ArrayBuilder.addToList, the compiler translates the varargs formal parameter T... elements to the formal parameter T[] elements, an array. However, because of type erasure, the compiler converts the varargs formal parameter to Object[] elements. Consequently, there is a possibility of heap pollution.

The following statement assigns the varargs formal parameter l to the Object array objectArgs:

Object[] objectArray = l;

This statement can potentially introduce heap pollution. A value that does match the parameterized type of the varargs formal parameter l can be assigned to the variable objectArray, and thus can be assigned to l. However, the compiler does not generate an unchecked warning at this statement. The compiler has already generated a warning when it translated the varargs formal parameter List<String>... l to the formal parameter List[] l. This statement is valid; the variable l has the type List[], which is a subtype of Object[].

Consequently, the compiler does not issue a warning or error if you assign a List object of any type to any array component of the objectArray array as shown by this statement:

objectArray[0] = Arrays.asList(42);

This statement assigns to the first array component of the objectArray array with a List object that contains one object of type Integer.

Suppose you invoke ArrayBuilder.faultyMethod with the following statement:

   ArrayBuilder.faultyMethod(Arrays.asList("Hello!"), Arrays.asList("World!"));

At runtime, the JVM throws a ClassCastException at the following statement:

   // ClassCastException thrown here
   String s = l[0].get(0);
Community
  • 1
  • 1
Amit Deshpande
  • 18,407
  • 4
  • 42
  • 69
  • 1
    There's nothing wrong with the signature of faultyMethod(), or the invocation of the method. What's wrong is inside the method body, but it has nothing to do with generic array creation. Since calling this vararg method requires creating a generic array, this is a loophole in the language spec. We can use it as a backdoor to legitimately create a generic array. http://stackoverflow.com/questions/529085/java-how-to-generic-array-creation/8052827#8052827 – irreputable Oct 09 '12 at 17:53
  • @irreputable Yes. I don't know why you have not received votes on that post :). – Amit Deshpande Oct 10 '12 at 06:52
3

Had you read further in that link, you would have found this statement: -

Pair<String,String> is not a reifiable type, that is, it loses information as a 
result of type erasure and is at runtime represented as the raw type Pair 
instead of the exact type Pair<String,String>

More from the JLS - Arrays: -

Discussion

If the element type of an array were not reifiable (§4.7), the virtual machine could not perform the store check described in the preceding paragraph. This is why creation of arrays of non-reifiable types is forbidden. One may declare variables of array types whose element type is not reifiable, but any attempt to assign them a value will give rise to an unchecked warning (§5.1.9).

Rohit Jain
  • 195,192
  • 43
  • 369
  • 489