I was just looking at the method defined in the List interface:
Returns an array containing all of the elements in this list in the correct order; the
As mentioned by others, there are a couple different reasons:
357 public <T> T[] toArray(T[] a) {
358 if (a.length < size)
359 // Make a new array of a's runtime type, but my contents:
360 return (T[]) Arrays.copyOf(elementData, size, a.getClass());
361 System.arraycopy(elementData, 0, a, 0, size);
362 if (a.length > size)
363 a[size] = null;
364 return a;
365 }
Maybe so it has a runtime type?
From wiki:
Consequently, instantiating a Java class of a parameterized type is impossible because instantiation requires a call to a constructor, which is unavailable if the type is unknown.
My guess is that if you already know the concrete type of T
at the point you're calling toArray(T[])
, it's more performant to just declare an array of whatever it is than make the List
implementation call Arrays.newInstance()
for you -- plus in many cases you can re-use the array.
But if it annoys you, it's easy enough to write a utility method:
public static <E> E[] ToArray(Collection<E> c, Class<E> componentType) {
E[] array = (E[]) Array.newInstance(componentType, c.size());
return c.toArray(array);
}
(Note that there's no way to write <E> E[] ToArray(Collection<E> c)
, because there's no way to create an array of E
at runtime without a Class
object, and no way to get a Class
object for E
at runtime, because the generics have been erased.)
Most likely this is to allow you to reuse arrays, so you basically avoid (relatively costly) array allocation for some use cases. Another much smaller benefit is that caller can instantiate array slightly more efficiently, since toArray() must use 'java.lang.reflect.Array.newInstance' method.
This method is a holdover from pre-1.5 Java. Here is the link to javadoc
Back then it was the only way to convert a list to a reifiable array.
It is an obscure fact, but although you can store anything in the Object[] array, you cannot cast this array to more specific type, e.g.
Object[] generic_array = { "string" };
String[] strings_array = generic_array; // ClassCastException
Seemingly more efficient List.toArray()
does just that, it creates a generic Object
array.
Before Java generics, the only way to do a type-safe transfer was to have this cludge:
String[] stronglyTypedArrayFromList ( List strings )
{
return (String[]) strings.toArray( new String[] );
// or another variant
// return (String[]) strings.toArray( new String[ strings.size( ) ] );
}
Thankfully generics made these kind of machinations obsolete. This method was left there to provide backward compatibility with pre 1.5 code.