转换 Arrays.asList 导致异常:java.util.Arrays$ArrayList 无法转换为 java.util.ArrayList
Posted
技术标签:
【中文标题】转换 Arrays.asList 导致异常:java.util.Arrays$ArrayList 无法转换为 java.util.ArrayList【英文标题】:casting Arrays.asList causing exception: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayList 【发布时间】:2011-10-02 05:32:18 【问题描述】:我是 Java 新手,我想了解为什么第一个代码 sn-p 不会导致此异常,但第二个代码会。由于在这两种情况下都将字符串数组传递给 Arrays.asList ,所以这两个 sn-ps 不应该产生异常还是不产生异常?
Exception in thread "main" java.lang.ClassCastException: java.util.Arrays$ArrayList cannot be cast to java.util.ArrayList
第一个sn-p(无异常):
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));
第二次sn-p(导致上述异常):
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。
【问题讨论】:
我在 IBM JDK 上,对我来说,即使是你的第一个 sn-p 也会出现同样的错误! 感谢您的所有回答。每个答案都有有用的信息,帮助我更好地理解 Java,并提醒我使用良好的编码风格。 【参考方案1】:对我来说(使用 Java 1.6.0_26),第一个 sn-p 给出了与第二个相同的异常。原因是Arrays.asList(..)
方法只返回List
,不一定是ArrayList
。因为您并不真正知道该方法返回的List
的类型(或实现),所以您对ArrayList<String>
的强制转换是不安全的。结果是它可能会或可能不会按预期工作。从编码风格的角度来看,一个很好的解决方法是将您的 stuff
声明更改为:
List<List<String>> stuff = new ArrayList<List<String>>();
这将允许添加来自Arrays.asList(..)
方法的任何内容。
【讨论】:
这个答案帮助我理解了其他答案关于编码到接口而不是实现以及我的转换是如何不安全的。 很好的解释。本页下方的另一个简单解决方案。【参考方案2】:如果您这样做,您将不会获得任何 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
包装返回的列表来克服这个问题。
【讨论】:
谢谢,@adarshr。我发现了这一点,但忘记在我的问题中发布它。我仍然对异常的原因感到好奇。 我认为这个答案更相关,因为 Arrays$ArrayList 表示在 Arrays 类中定义的内部类 ArrayList。【参考方案3】:问题是您指定列表包含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));
我已经测试了这段代码,它运行没有错误。
【讨论】:
如何确定使用 new ArrayList> 而不是 new List> 或 new List>? @DannyTree Javanew
关键字创建一个类的新实例。为此,该类必须是“具体的”(如“非抽象”)。这基本上意味着它可能没有“松散的结局”,所有方法都必须有实现。当您说new List<ArrayList<String>>
时,您没有指定要实例化List
的哪种,所以这不起作用。【参考方案4】:
无需手动投射。这个简单的代码可能会对你有所帮助,
List stuff = new ArrayList();
String line = "a,b,cdef,g";
String delim = ",";
stuff.addAll(Arrays.asList(line.split(delim)));
【讨论】:
【参考方案5】:使用调试器,我确定 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));
【讨论】:
【参考方案6】:如果你想将你的属性用作 ArrayList 你只需要在那里声明并创建一个 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;
初始化变量,使用方法[addAll(Collection collection)](http://developer.android.com/intl/pt-br/reference/java/util/ArrayList.html#addAll(java.util.Collection))
【讨论】:
如果您无法将 ArrayList 更改为 List,这是一个很好的解决方法。【参考方案7】:首先,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));
要快乐。
【讨论】:
以上是关于转换 Arrays.asList 导致异常:java.util.Arrays$ArrayList 无法转换为 java.util.ArrayList的主要内容,如果未能解决你的问题,请参考以下文章