Home > other >  ClassCastException in List.toArray()
ClassCastException in List.toArray()

Time:04-27

Can someone explain to me:

List<String> wordsList = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
String[] wordsArray = (String[]) wordsList.toArray();

This fall with: Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

 List<String> wordsList = Arrays.asList("one", "two", "three");        
 String[] wordsArray = (String[]) wordsList.toArray();

Now is OK! What is the difference??

CodePudding user response:

toArray() is the old way of doing things, back in I think 1.5 the preferred way is to use toArray(T[])

List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
String [] words = list.toArray(new String[] {});
System.out.println(Arrays.toString(words));

CodePudding user response:

List.toArray returns an Object[]. This type cannot, in general, be cast down to a String[]. In fact, no guarantee is made that it is a String[]. In your Arrays.asList example, it looks like List<String> was able to take the existing array you passed it and make a (runtime) String[], but that's an implementation detail and is subject to change at any time (and, based on the comments, is not even consistent across Java versions).

The reason the function returns an Object[] rather than a T[] is because of type erasure. The type T is not available at runtime, so we can't construct instances of T or T[]. However, there's an overload of toArray which will put the values into a T[], but you have to supply the array. This gets around the problem of not being able to write new T[], since it's your job as the caller to supply the array, so no new allocation needs to take place.

String[] tmpArray = new String[10]; // Just an initial guess as to the size
String[] wordsArray = list.toArray(tmpArray); // Note: No cast necessary

wordsArray might be the same as tmpArray, or it might be an extended data structure constructed from tmpArray. Either way, the original tmpArray should be regarded as destroyed at that point and not used anymore.

Note: The fact that String[] is even a subtype of Object[] (i.e. that the cast you suggested ever works) is a consequence of a questionable decision that the Java team made to make arrays covariant, when really a mutable data structure like that should be invariant, mathematically speaking.

  •  Tags:  
  • java
  • Related