Reputation: 13
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.
Upvotes: 1
Views: 230
Reputation: 31699
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 ArrayList
s.
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.
Upvotes: 2
Reputation: 85809
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 String
s 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.
Upvotes: 7