When you ask yourself what should be the type of the array in toArray()
, the first, most obvious way is to restrict T
to be a supertype of E
(which includes if T
is the same as E
): This makes sense -- to be able to copy the elements to an array of a more general element type than our collection. However, although this seems type-safe (i.e. checked at compile time so that no exceptions occur at runtime) at first glance, it is not completely type-safe -- a variable of type T[]
can hold any array of type U[]
where U
is a subtype of T
. Thus, it is still possible to get an ArrayStoreException
even if we limit T
to supertypes of E
(and, even if we limit T
to be the same as E
). Plus, it is difficult to declare this method in such a way that T
can only be a supertype of E
, since Java does not allow super
bounds for type parameters.
The example in the question involves a T
that is not a supertype of E
. Why should this be allowed? This is not type-safe, and will work only if the elements of the collection are actually subtypes of the actual type of the array. However, it can be argued that this is still no worse than the situation where we restrict T
to a supertype of E
, or even if we have T
be the same as E
, because, as explained above, none of those restrictions can make it type-safe either. It's possible to get ArrayStoreException
no matter how you declare this method. So why not make it as general as possible, if it's no worse?