• Post Reply Bookmark Topic Watch Topic
  • New Topic

ArrayList.toArray() vs. ArrayList.toArray(T[] a)  RSS feed

 
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I need an array of the object references stored in my ArrayList. Using the one-argument version of the toArray method works, but casting the result of the no-argument version to the type of object contained in the ArrayList generates a ClassCastException, even though up- and down-casting the individual objects does not.

Here's a SSCCE:



Running it gets me this:

Hello world
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
at casts.ArrayTest.main(ArrayTest.java:18)


I had expected lines 17 and 18 to be functionally identical, and would welcome some help in understanding why they are not.
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Heh. Looking at the error message a little more closely made me realize this has nothing to do with ArrayList methods. This code produces the same error (and means this question probably should be in the Beginning Java forum):



Output:

Hello world
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
at casts.ArrayTest.main(ArrayTest.java:14)

 
Java Cowboy
Sheriff
Posts: 16060
88
Android IntelliJ IDE Java Scala Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That error means: "I have an array of Object, you are trying to cast it to an array of String, but I can't do that because an Object array is not a String array".

Just because the Object array happens to contain one object which is a String, doesn't mean that the array is suddenly a String array. So you can't cast it to a String array.
 
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Java arrays are covariant. Which means, for example, that a String[] is-an Object[], because a String is-an Object. But an Object[] is-not-a String[] any more than an Object is-a String, even if the array only contains Strings. Arrays are objects in their own right, separate from their contents, and have a corresponding type.

So if something is created as an Object[] it can't be cast to a String[], for exactly the same reason that you can't create a new Object and then cast it to a String.

That's exactly why the toArray() method has two versions. With no arguments, it will create an Object[] and put the contents into it. A cast to a different type of array won't be valid. The version with an argument will create an array specifically of the given type (e.g. String[]). Before generics were introduced, that method was declared to return an Object[], and returning the more specific array was fine because of the covariance, and then the cast would work. Since generics were introduced the cast isn't needed in that case.

 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks! I misled myself by thinking that an array of Object references would naturally all be to the same class. Clearly not so. This bit, based on what you just helped me understand, makes the error clearer to me:



Line 14 compiles, but creates the same impossible down-cast problem at run-time.

Thanks again, Jesper and Matthew.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!