Why is toArray() a Generic Method in Java Collections?

Here’s something that caught my eye in the Java Collections API:

<T> T[] toArray(T[] a)

The collection is already parameterized — List<E>, Set<E>, etc. So why does toArray need to declare its own type parameter T? Why isn’t it just:

E[] toArray(E[] a)

I wrote a simple AList<E> generic class to experiment:

public class AList<E> {
    private Object[] elements;
    private int size;

    public <T> T[] toArray(T[] a) {
        System.arraycopy(elements, 0, a, 0, size);
        return a;
    }
}

Both the pre-Java 5 untyped version and the Java 5 generic version worked in my tests. But that didn’t answer the underlying question — why the extra type parameter?

The answer involves some interesting subtleties about Java’s type system, supertype bounds, and the PECS principle. I posted the question to CinJUG and got some great responses — I’ll write up the full explanation in a follow-up post.

Teaser: it has to do with allowing callers to pass in an array of a supertype of the collection’s element type, which turns out to be genuinely useful in practice.

See the answer post for the full breakdown.