casting Arrays.asList causing exception: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayList

77,067

Solution 1

For me (using Java 1.6.0_26), the first snippet gives the same exception as the second one. The reason is that the Arrays.asList(..) method does only return a List, not necessarily an ArrayList. Because you don't really know what kind (or implementation of) of List that method returns, your cast to ArrayList<String> is not safe. The result is that it may or may not work as expected. From a coding style perspective, a good fix for this would be to change your stuff declaration to:

List<List<String>> stuff = new ArrayList<List<String>>();

which will allow to add whatever comes out of the Arrays.asList(..) method.

Solution 2

If you do this, you won't get any CCE:

ArrayList<ArrayList<String>> stuff = new ArrayList<ArrayList<String>>();
String[] titles = {"ticker", "grade", "score"};
stuff.add(new ArrayList<String>(Arrays.asList(titles)));

As the error clearly states, the class java.util.ArrayList isn't the same as nested static class java.util.Arrays.ArrayList. Hence the exception. We overcome this by wrapping the returned list using a java.util.ArrayList.

Solution 3

The problem is you specified your List to contain ArrayLists - and by implication no other List implementations. Arrays.asList() returns its own implementation of a List based on the implementation of the array parameter, which may not be an ArrayList. That's your problem.

More broadly, you have a classic code style problem: You should be referring to abstract interfaces (ie List), not concrete implementations (ie ArrayList). Here's how your code should look:

List<List<String>> stuff = new ArrayList<List<String>>();
String[] titles = { "ticker", "grade", "score" };
stuff.add((List<String>) Arrays.asList(titles));

I have tested this code, and it runs without error.

Solution 4

No need to cast manually. This simple code may help you,

List stuff = new ArrayList();
String line = "a,b,cdef,g";
String delim = ",";
stuff.addAll(Arrays.asList(line.split(delim)));

Solution 5

Using a debugger, I determined that Array.asList(titles) returns an "Arrays$ArrayList" (ie an inner class of the Arrays class) rather than a java.util.ArrayList.

It's always best to use the interface on the left side of expressions, in this case List rather than the concrete ArrayList. This works fine:

    List<List<String>> stuff = new ArrayList<List<String>>();
    String[] titles = {"ticker", "grade", "score"};
    stuff.add((List<String>) Arrays.asList(titles));
Share:
77,067
DannyTree
Author by

DannyTree

Updated on January 25, 2020

Comments

  • DannyTree
    DannyTree over 4 years

    I'm new to Java and am trying to understand why the first code snippet doesn't cause this exception but the second one does. Since a string array is passed into Arrays.asList in both cases, shouldn't both snippets produce an exception or not produce an exception?

    Exception in thread "main" java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayList
    

    First snippet (causes no exception):

    ArrayList<ArrayList<String>> stuff = new ArrayList<ArrayList<String>>();
    String line = "a,b,cdef,g";
    String delim = ",";
    String[] pieces = line.split(delim);
    stuff.add((ArrayList<String>) Arrays.asList(pieces));
    

    Second snippet (causes above exception):

    ArrayList<ArrayList<String>> stuff = new ArrayList<ArrayList<String>>();
    String[] titles = {"ticker", "grade", "score"};
    stuff.add((ArrayList<String>) Arrays.asList(titles));
    

    If relevant, I'm using JavaSE 1.6 in Eclipse Helios.

  • DannyTree
    DannyTree almost 13 years
    Thanks, @adarshr. I had discovered that but forgot to post it in my question. I'm still curious as to the cause of the exception.
  • DannyTree
    DannyTree almost 13 years
    how do you determine to use new ArrayList<List<String>> rather than new List<ArrayList<String>> or new List<List<String>>?
  • DannyTree
    DannyTree almost 13 years
    This answer is the one that helped me understand what the other answers were saying about coding to an interface rather than to an implementation and how my casting was unsafe.
  • Waldheinz
    Waldheinz almost 13 years
    @DannyTree The Java new keyword creates a new instance of a class. To do so, the class has to be "concrete" (as in "not abstract"). This basically means that it may not have "loose ends", all methods must have implementations. When you say new List<ArrayList<String>>, you don't specify which kind of List you want to instantiate, so this does not work.
  • MohamedSanaulla
    MohamedSanaulla about 11 years
    I think this answer is more relevant because Arrays$ArrayList represents an inner class ArrayList defined in Arrays class.
  • GFPF
    GFPF over 8 years
    Good explanation. Another simple solution below in this page.
  • Pierre C
    Pierre C over 7 years
    This is a good workaround if you cannot change your ArrayList to List.