1

Putting different types of Objects into an array will throw an ArrayStoreException, while putting different types of objects into an ArrayList works.

As far as I know, the ArrayList is built on top of an array, so why does it work there? Is it implemented differently?

I searched but found no answer.

1
  • 2
    Are you comparing apples to apples? I.e. Object[] to ArrayList<Object>? Commented Aug 11, 2014 at 23:29

2 Answers 2

7

ArrayList has a field called Object[] elementData which means an ArrayList supports adding every kind of object reference. This also means that ArrayList doesn't support primitive types such as int or char, but instead their wrapper classes Integer and Character, respectively.

Arrays are usually for single-type elements since their declaration, unless you declare them as Object[]. For primitive types, there's no generic array, just the arrays of primitives int[], char[] and on...


if you create an Object[] array, and put in strings and afterwards a date object, it will throw an exception

Here's a code that proves the contrary, compiles and executes with no problem by having an Object[] storing Strings and a Date:

Object[] objects = { "hello", "world", new Date() };
System.out.println(Arrays.toString(objects));

Output (the Date will depend on the current time of your pc):

[hello, world, Tue Aug 12 00:09:00 GMT 2014]

You can check it working here.

5
  • Just a question, aren't ArrayLists templated? Doesn't that mean that it has a T[] elementData instead, unless you define T as Object? Or is the template optional and it defaults to Object[]? Commented Aug 11, 2014 at 23:32
  • 4
    @StealthyHunter7 that's for compilation purpose, so you can't insert an Integer into a List<String>. But at runtime, they get type erasured and become raw types. Commented Aug 11, 2014 at 23:34
  • 1
    I mean, if you create an Object[] array, and put in strings and afterwards a date object, it will throw an exception, but this doesnt happen with ArrayList<Object> or an ArrayList without generics(It will simply replace T with Object)
    – Dero Leaq
    Commented Aug 11, 2014 at 23:35
  • 1
    @DeroLeaq I updated the answer with a code that proves the contrary. If you happen to encounter such problem, please provide a piece of code that demonstrates this error to analyze it and provide a solution for it. Commented Aug 11, 2014 at 23:39
  • Thank you very much for explaing, after seing your example I got my code working!
    – Dero Leaq
    Commented Aug 11, 2014 at 23:44
2

An ArrayStoreException can only arise when you've cast an array SomeClass[] to an array TheSuperClass[]. It doesn't get thrown in other situations. For example:

A[] array = new A[100];

The elements of array can be objects of class A or any subclass of A, and you'll never get ArrayStoreException. Similarly:

Object[] array = new Object[100];

The elements of this array can be anything. No matter what you assign array[n] to, this won't throw an ArrayStoreException.

The issue comes when you use new to create an array of one type, and then cast it (perhaps implicitly) to an array of some superclass type:

A[] array = new B[100];   // legal if B is a subclass of A
C[] array2 = new C[100];  
Object[] array3;
array3 = array2;          // legal even though `array2` is C[]

This kind of cast is legal. BUT if you then try to assign something that doesn't fit into the type used to create the array, you'll get ArrayStoreException.

array[1] = new A();

The only things that can be assigned into array[n] are B or subclasses of B. The compiler can't catch the above error at compile time, but it throws an exception at runtime.

array3[1] = "some string";

Even though array3 is an Object[] array, you can't assign any old object to its elements; they have to be C or subclasses of C.

The reason this isn't a problem with ArrayList is that you just can't do the same kind of cast.

ArrayList<A> array = new ArrayList<B>();   // illegal even if B is a subclass of A
ArrayList<C> array2 = new ArrayList<C>();
ArrayList<Object> array3;
array3 = array2;  // illegal

So it's not really a matter of arrays being more restricted than ArrayList. Arrays have an exception in a situation that just can't come up with ArrayLists.

EDIT (based on Luiggi's comment): OK, it looks like you can force the wrong kind of object into an ArrayList with some trickery:

((ArrayList)array2).add(x);

where x can have any type; it doesn't have to be of type C. But never, never, never do this. Especially in any program I might have to maintain one day.

2
  • Note that you can still add Object elements in array2 and make it w/o a compiler exception nor a runtime exception, no reflection involved. Commented Aug 11, 2014 at 23:46
  • Thank you for your detailed answer! Indeed my problen was an api method casting the array without me knowing it so I didn't recognize it(like you would with generics)
    – Dero Leaq
    Commented Aug 11, 2014 at 23:48

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.