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
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
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.
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);
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).