2
private static void genericArrayTest() {
    ArrayList<? extends Exception>[] exceptionListArray = new ArrayList[10]; 
    Object[] exceptionObjectListArray  = exceptionListArray;

    ArrayList<String> wrongArrayList = new ArrayList<String>();
    wrongArrayList.add("String One");

    ArrayList<NullPointerException> exceptionList = new ArrayList<>();

    ArrayList rawList = new ArrayList();

    exceptionListArray[0] = exceptionList;
    //exceptionListArray[0] = wrongArrayList; // Compile error?
    //exceptionListArray[0] = rawList;

    exceptionObjectListArray[0] = wrongArrayList; 
// No compile time error, there is no ArrayStoreException why ?

    ArrayList<? extends Exception> list = exceptionListArray[0]; // No exception here as well ??
    Exception e = list.get(0); 
// Exception only when accessing data, why not ArrayStoreException when we stored wrong list ??
    System.out.println();
}

Can someone please explain what is going on ?

Google search says below array declaration is allowed
ArrayList<Exception>[] exceptionListArray = new ArrayList[10];
but not this
ArrayList<Exception>[] exceptionListArray = new ArrayList<Exception>[10];
What is the difference between these two declaration & why one is allowed not other one?

Creating an array to store generic types in Java is talks about how to create generic array. But this question is not about how to create generic array, its about why ArrayStoreException is not thrown at runtime & difference in generic array creation syntax in java

4
  • Check here for your last question: stackoverflow.com/a/16415586/986169. Regarding exceptionObjectListArray, it is declared as an array of Object types. So any array of a type that extends Object can be assigned to it. Commented May 3, 2015 at 13:32
  • @giorashc From above link, I got into - docs.oracle.com/javase/tutorial/java/generics/…. It says "If arrays of parameterized lists were allowed, code would fail to throw the desired ArrayStoreException". But, it is happening now as well with above code block correct ? So the question is what does java achieved by allowing 'ArrayList<Exception>[] exceptionListArray = new ArrayList[10]; ' ? Commented May 3, 2015 at 13:37
  • possible duplicate of Creating an array to store generic types in Java Commented May 3, 2015 at 13:58
  • I don't think that's a complete duplicate because this question asks about ArrayStoreException. Commented May 3, 2015 at 14:40

1 Answer 1

3

In Java, generic parameterizations do not have a class which distinguishes them from each other:

ArrayList<Exception> : class is ArrayList
ArrayList<String>    : class is ArrayList

This is because generics are implemented with type erasure, which means that during compilation, they are replaced with casting:

ArrayList<Exception> list = new ArrayList<Exception>();
list.add(new Exception());
Exception e = list.get(0);

becomes:

ArrayList list = new ArrayList();
list.add(new Exception());
Exception e = (Exception) list.get(0);

No ArrayStoreException is thrown because ArrayList<Exception> and ArrayList<String> have the same type during program execution.

A generic array is disallowed because there is no way to perform these checks on the type parameters during execution. (Because the type parameters don't exist anymore.)

When we have this:

ArrayList<Exception>[] a =
    new ArrayList[10];

It's called an unchecked conversion. a is actually an ArrayList[], an array which stores any ArrayList but we've basically said "pretend it's an ArrayList<Exception>[] for the time being". The array object a points to is still an ArrayList[].


See the following program to illustrate:

import java.util.*;

class Example {
    public static void main(String[] args) {
        ArrayList<Exception> a = new ArrayList<Exception>();
        ArrayList<String>    b = new ArrayList<String>();

        System.out.println("ArrayList<Exception> class is:");
        System.out.println("\t" + a.getClass());
        System.out.println("ArrayList<String> class is:");
        System.out.println("\t" + b.getClass());
        System.out.println(
            "ArrayList<Exception> class == ArrayList<String> class:");
        System.out.println("\t" + ( a.getClass() == b.getClass() ));

        ArrayList<Exception>[] c = new ArrayList[0];
        ArrayList<String>[]    d = new ArrayList[0];

        System.out.println("ArrayList<Exception>[] class is:");
        System.out.println("\t" + c.getClass());
        System.out.println("ArrayList<String>[] class is:");
        System.out.println("\t" + d.getClass());
        System.out.println(
            "ArrayList<Exception>[] class == ArrayList<String>[] class:");
        System.out.println("\t" + ( c.getClass() == d.getClass() ));
    }
}

http://ideone.com/dfCZjy

Output:

ArrayList<Exception> class is:
    class java.util.ArrayList
ArrayList<String> class is:
    class java.util.ArrayList
ArrayList<Exception> class == ArrayList<String> class:
    true
ArrayList<Exception>[] class is:
    class [Ljava.util.ArrayList;
ArrayList<String>[] class is:
    class [Ljava.util.ArrayList;
ArrayList<Exception>[] class == ArrayList<String>[] class:
    true
Sign up to request clarification or add additional context in comments.

11 Comments

Type erasure or not, every class in Java extends from Object. I guess that should be sufficient to explain why an ArrayStoreException is not thrown.
@ChetanKinger I don't really see how that's relevant.
@ChetanKinger That's not relevant because the class of exceptionObjectListArray is ArrayList[], not Object[]. It is possible to get an ArrayStoreException for an array with compile-time type Object[].
@pbabcdefp Can you elaborate on what you mean by the class of exceptionObjectListArray is ArrayList[]? Do you mean at runtime because at compile time, it is an Object[] array right?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.