39

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.

2
  • 2
    I'm on IBM JDK and for me even your first snippet gives the same error! Commented Jul 10, 2011 at 12:18
  • 1
    Thanks for all your answers. Each answer had helpful information and is helping me to better understand Java and a reminder to use good coding style. Commented Jul 10, 2011 at 12:35

7 Answers 7

31

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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.
Good explanation. Another simple solution below in this page.
10

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.

2 Comments

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.
I think this answer is more relevant because Arrays$ArrayList represents an inner class ArrayList defined in Arrays class.
10

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.

2 Comments

how do you determine to use new ArrayList<List<String>> rather than new List<ArrayList<String>> or new List<List<String>>?
@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.
8

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)));

Comments

1

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));

Comments

1

If you want to use your property as ArrayList<'T'> you need only declare there and create a getter.

    private static ArrayList<String> bandsArrayList;

    public ArrayList<String> getBandsArrayList() {
        if (bandsArrayList == null) {
            bandsArrayList = new ArrayList<>();

            String[] bands = {"Metallica", "Iron Maiden", "Nirvana"};
            bandsArrayList.addAll(Arrays.asList(bands));
        }
        return bandsArrayList;
    }

Initializes the variable and use the method [addAll (Collection collection)](http://developer.android.com/intl/pt-br/reference/java/util/ArrayList.html#addAll(java.util.Collection))

1 Comment

This is a good workaround if you cannot change your ArrayList to List.
0

First, Arrays.asList() should be never casted to ArrayList. Second, since generics were introduced into java programming language casting is still relevant when using legacy, pre-generics APIs.

Third, never use concrete classes at the left of assignment operator.

Bottom line, say

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



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

and be happy.

Comments

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.