转换Arrays.asList导致异常:java.util.Arrays $ ArrayList无法强制转换为java.util.ArrayList

时间:2011-07-10 12:10:22

标签: java arrays casting multidimensional-array arraylist

我是Java新手,我试图理解为什么第一个代码片段不会导致此异常,但第二个代码片段会导致此异常。由于在两种情况下都将字符串数组传递给Arrays.asList,因此两个片段是否都不会产生异常或不产生异常?

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

第一个片段(没有例外):

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

第二个片段(导致上述异常):

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

如果相关,我在Eclipse Helios中使用JavaSE 1.6。

7 个答案:

答案 0 :(得分:31)

对我来说(使用Java 1.6.0_26),第一个片段提供与第二个片段相同的异常。原因是Arrays.asList(..)方法只返回List,不一定是ArrayList。因为您实际上并不知道该方法返回的List的类型(或 的实现),所以您对ArrayList<String>的强制转换是不安全的。结果是它可能会或可能不会按预期工作。从编码风格的角度来看,一个很好的解决方法是将stuff声明更改为:

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

允许添加Arrays.asList(..)方法中的任何内容。

答案 1 :(得分:10)

如果你这样做,你就不会得到任何CCE:

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

由于错误明确指出,类java.util.ArrayList与嵌套静态类java.util.Arrays.ArrayList不同。因此例外。我们通过使用java.util.ArrayList包装返回的列表来克服这个问题。

答案 2 :(得分:10)

问题是您指定列表包含ArrayLists - 并暗示没有其他列表实现Arrays.asList()基于数组参数的实现返回其自己的List实现,其中可能不是 ArrayList。那是你的问题。

更广泛地说,您有一个典型的代码样式问题:您应该引用抽象接口(即List),而不是具体实现(即ArrayList)。以下是代码的外观:

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

我已经测试了这段代码,它运行时没有错误。

答案 3 :(得分:8)

无需手动投射。这个简单的代码可以帮到你,

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

答案 4 :(得分:1)

使用调试器,我确定Array.asList(titles)返回“Arrays $ ArrayList”(即Arrays类的内部类)而不是java.util.ArrayList。

最好使用表达式左侧的接口,在本例中为List而不是具体的ArrayList。这很好用:

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

答案 5 :(得分:1)

如果您想将您的属性用作ArrayList&lt;&#39; T&#39;&gt;你只需要在那里声明并创建一个吸气剂。

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

初始化变量并使用方法[addAll(Collection collection)](http://developer.android.com/intl/pt-br/reference/java/util/ArrayList.html#addAll(java.util.Collection))

答案 6 :(得分:0)

首先,Arrays.asList()永远不应该转换为ArrayList。其次,由于将泛型引入到java编程语言中,因此在使用传统的预泛化API时仍然需要进行转换。

第三,从不使用赋值运算符左侧的具体类。

底线,说

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

并且快乐。