Why can't I create an array of general type?

In short, this does not compile:

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

Is it due to backward compatibility issues or is it something fundamental in the language design that prevents it?

+8
java language-design
source share
5 answers

The bottom line is that the class representing the array must know the type of component. Therefore, the method of 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 try:

  A[] a = new A[0]; 

At compile time, it is obvious that we do not know the type, since this is a general parameter. At run time, we do not know the type due to the erasure of the type. Thus, creating an instance of the array is not possible.

Recall the above statement as equivalent:

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

And due to type erasure, we cannot get class A at runtime.

It was asked, why not compile the compiler for Object [] or Number [] or something like that?

This is because, depending on the type of component, another class will be returned. So:

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

are not the same class. In particular, the getComponentType () method in the class returns different values.

So, if you reduce it to Object [] instead of A [], you will not actually get something like A [], you will return Object []. The [] object cannot be compiled by Integer [] and will throw a ClassCastException.

+5
source share

Type erasure is the word you are looking for. This basically means that generic information is deleted at compile time. The main reason for this is backward compatibility. Old programs should still run on the new Java virtual machine.

+5
source share

This does not work for the same (or almost the same) reason that new A() cannot work: you expect the compiler to recognize the type of runtime A that it does not explicitly know. This will work if Java Generics is similar to C ++ templates, where new code is created for each instance of the template involving A

+1
source share

In Java, the type system for arrays and generics is not compatible. There are two main areas of discrepancy: dynamic and static type checking and covariance .

Static notations are checked statically: that is, the compiler ensures that type definitions are coherent. Type Erasure was a compromise for backward compatibility in the JVM. After compilation, a generic type definition is no longer available. For example. A list becomes a list.

In contrast, arrays are dynamically checked by type. Consider the following example:

 String strings[] = {"a","b","c"}; Object simple[] = strings; simple[0] = new Object(); // Runtime error -> java.lang.ArrayStoreException 

Covariance is the relationship of inheritance of a container based on content. For types A, B and container C, if B AAssignableFrom (A) => C isAssignable C.

Arrays in Java are covariant in the previous example. Given that Class<Object>.isAssignableFrom(Class<String>) => Object[] is assignable from String[]

In contrast, generic types are not covariant in Java. Using the same example:

 List<String> stringList = new ArrayList<String>(); List<Object> objectList = stringList; // compiler error - this is not allowed. 

Given the erasure of the generic implementation type, the type information is lost during translation, and therefore the dynamic type check would be compromised if you could create an array of a general type.

Read on about the complications and consequences of these problems: Arrays in Java Generics

+1
source share

Yes, there is a fundamental reason that comes down to type erasure .

Consider the following snippet:

 A[] temp = new A[5]; // Assume this would compile. Object[] objects = temp; // This is allowed, since A extends Object. objects[0] = new String(); // This does *not* throw an ArrayStoreException // due to type erasure since the original type of A // is now Object. A t = temp[0]; // Now this seemingly innocent line would *fail*. 

Related Question:

  • How to create a shared array in Java?
0
source share

All Articles