Why does the Java Collection <E> .toArray () return an object [] rather than E []?
Prior to generating Java, Collection.toArray() had no way of knowing what type of array the developer was expecting (especially for an empty collection). As far as I understand, this was the main argument in favor of the idiom collection.toArray(new E[0]) .
With the generics Collection<E>.toArray() can return an array full of instances of E and / or its specializations. I wonder why the return type is still equal to Object[] , not E[] . In my opinion, returning E[] instead of Object[] should not violate existing code.
See: Collection.toArray() , Collection.toArray(T[]) and related java theme : (String []) List.toArray () provides a ClassCastException
This is a very good question. The answer is that generics are also called βerasuresβ. This is not just a name. Generically encoded information is only used at compile time and then deleted. Thus, the JVM does not even know this generic type E , so it cannot create an array E[] .
Another toArray(T[] a) method gets type information from an argument at runtime. For this reason, the prototype of this method is <T> T[] toArray(T[] a) : it receives an array of type T and can return an array of type T. The type is passed as a parameter.
Erasing a type is just a partial explanation: neither the Collection method nor its toArray() have any information about E at run time.
In addition, due to backward compatibility, Collection.toArray() should return Object[] . Prior to Java 1.5, there was no way to find out the general type for a collection, so this was the only reasonable API design.
@Lukas, regarding: "new E []"
The new E [0] raised a compiler error, as you probably expected. The workaround I found is:
final E [] returnArray = (E []) events.toArray (new event [events.size ()]);
NB code is in the Listener <E extends Event> template class.
On my workaround, the erase type is both a problem and a solution. Casting to (E []) is safe because its exact type is erased before Event []. The only drawback that I see is the compiler warning about "unverified or unsafe operations" (which, obviously, in this case the cast does not work when the type is erased).
@Lukas, regarding backward compatibility
I do not see a big problem with backward compatibility. Creating a special return type is not the same as making the argument type more special.
In other words, the source code, which until now expected Collection.toArray () to return Object [], should be happy to get E [].
And as for the byte code, Object [] and E [] are the same anyway due to type erasure.