Why does Collection<E>.toArray()
(non-parameterized method) return Object[]
?
Is it one of those consciously taken decisions? Is there any reason why the toArray()
method would not be able to return a E[]
, if it wanted to?
Why does Collection<E>.toArray()
(non-parameterized method) return Object[]
?
Is it one of those consciously taken decisions? Is there any reason why the toArray()
method would not be able to return a E[]
, if it wanted to?
It's because an array of type T
cannot be instantiated without knowing the type Class<T>
. Contrast this with toArray(T[] array)
, which has the following source (example from LinkedList
). Notice that the passed-in array is used not only as a possible container, but to possibly instantiate a new array of that type. This code throws an exception if T
is not a superclass of E
; if objects can't be added to the array.
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size)
a = (T[])java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), size);
int i = 0;
Object[] result = a;
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
if (a.length > size)
a[size] = null;
return a;
}
Generics in Java are implemented using a technique called type erasure. This means that an instance of a generic class does not have any information about its generic type. Consider this
List<String> list = new ArrayList<String>();
list.toArray();
since list does not know about its generic type it can create only Object[]
Array containers have an associated item data type, preserved at runtime. If you construct an Object array and then add strings, this object won't be castable to String[]:
Object[] objArr = new Object[] {"a", "b"};
String[] strArr = (String[]) objArr; //Produces ClassCastException
You can also notice how this array property is used at runtime when you add items of an incorrect type to an array:
String[] strArr = new String[] {"a", "b"};
Object[] objArr = (Object[]) strArr; //Legal this time
objArr[0] = 15; //Produces ArrayStoreException
Generic type arguments are erased at runtime, so the JVM doesn't know what specific array type to create at runtime when you call toArray().