Consider the following test of Java's ArrayList#toArray method. Note that I borrowed the code from this helpful answer.

public class GenericTest {
    public static void main(String [] args) {
        ArrayList<Integer> foo = new ArrayList<Integer>();
        Integer[] bar = foo.toArray(new Integer[10]);
        System.out.println("bar.length: " + bar.length);

        for(Integer b : bar) { System.out.println(b); }

        String[] baz = foo.toArray(new String[10]);       // ArrayStoreException
        System.out.println("baz.length: " + baz.length);

But, notice that there will be a ArrayStoreException when trying to put an Integer into a String[].


$>javac GenericTest.java && java -cp . GenericTest
bar.length: 10
Exception in thread "main" java.lang.ArrayStoreException
        at java.lang.System.arraycopy(Native Method)
        at java.util.ArrayList.toArray(Unknown Source)
        at GenericTest.main(GenericTest.java:16)

Can this error be prevented through Java generics at compile-time?


ArrayStoreException exists precisely because Java's type system cannot handle this situation properly (IIRC, by the time Generics came along, it was too late to retrofit arrays in the same manner as the collections framework).

So you can't prevent this problem in general at compile time.

You can of course create internal APIs to wrap such operations, to reduce the likelihood of accidentally getting the types wrong.

See also:

  • You write "because Java's type system cannot handle this situation properly". What is the explanation for that? – mrbela May 7 at 12:54
  • There's quite a lot of detail and background in the linked question ("Why are arrays covariant...") but essentially it's for historical reasons that made sense at the time... – DNA May 7 at 16:15

List#toArray(T[]) is a generic method declared as

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

So the type argument is either inferred from the type of the given array or with the <Type> notation prefixing the method invocation.

So you could do

String[] baz = foo.<Integer>toArray(new String[10]); // doesn't compile

But I think that's the best you could do.

But in that sense, you can clearly see that Integer doesn't match String (or vice-versa).

Note that this is a documented exception

ArrayStoreException - if the runtime type of the specified array is not a supertype of the runtime type of every element in this list

So I don't think you should be trying to find it at compile time.


The method Collection.toArray cannot be changed for compatibility reasons.

However for your own code you can create a (more) type-safe helper method which protects you from the ArrayStoreException if you use your method consequently:

public static <T> T[] toArray(List<? extends T> list, T[] t) {
    return list.toArray(t);

This method will reject String[] s=toArray(new ArrayList<Integer>(), new String[0]); which matches the example case of your question, but beware of the array subtyping rule: it will not reject


because of the pre-Generics “String[] is a subclass of Object[]” rule. This can’t be solved with the existing Java language.

  • 2
    Any explanation for the downvote? – Holger Feb 19 '14 at 8:25

The ArrayStoreException is runtime exception not compile time and thrown at run time and it indicates that different type of object is being stored in the array. Object x[] = new String[3]; x[0] = new Integer(0); The only way you can find it at compile time is by using <Integer> type as below


The above will throw compile time error as The parameterized method <Integer>toArray(Integer[]) of type List<Integer> is not applicable for the arguments (String[]).

Your Answer

