Java集合ArrayList,LinkedList强制转换异常

Java集合ArrayList,LinkedList强制转换异常,java,arraylist,collections,classcastexception,Java,Arraylist,Collections,Classcastexception,我发现了一个至今无法解释的奇怪案例 public static void main(String[] args) { LinkedList<Integer> a = new LinkedList<>(); a.add(2); a.add(3); a.add(4); for (ArrayList ax : getBatches(a)){ System.out.println(ax); } } priva

我发现了一个至今无法解释的奇怪案例

 public static void main(String[] args) {
    LinkedList<Integer> a = new LinkedList<>();
    a.add(2);
    a.add(3);
    a.add(4);

    for (ArrayList ax : getBatches(a)){
        System.out.println(ax);
    }

}

private static ArrayList<ArrayList<Integer>> getBatches(List<Integer> optionIds) {
        return new ArrayList(Arrays.asList(optionIds));
}
publicstaticvoidmain(字符串[]args){
LinkedList a=新建LinkedList();
a、 增加(2);
a、 增加(3);
a、 增加(4);
对于(ArrayList ax:getBatches(a)){
系统输出打印LN(ax);
}
}
私有静态ArrayList getBatches(列表选项ID){
返回新的ArrayList(Arrays.asList(optionId));
}
执行的结果是:

线程“main”java.lang.ClassCastException中的异常:无法将java.util.LinkedList转换为java.util.ArrayList

异常进入for循环


问题是:如何?返回类型为ArrayList>的方法如何返回LinkedList?

您的方法返回原始
ArrayList
,这就是编译器允许它的原因。但是,在运行时,会尝试将
LinkedList
(传递给
getBatches
方法的实例)强制转换为
ArrayList
,从而导致
ClassCastException

如果将方法更改为:

private static ArrayList<ArrayList<Integer>> getBatches(List<Integer> optionIds) {
    return new ArrayList<>(Arrays.asList(optionIds));
}
这将返回一个
ArrayList
,其单个元素是
ArrayList
,包含与传递给方法的
列表相同的元素。

getBatches()
将返回一个泛型类型为
ArrayList
的ArrayList。
Arrays.asList()
的返回类型是一个
List
接口。为了从列表到ArrayList,它需要进行隐式转换。问题是不能直接将ArrayList强制转换为LinkedList

解决这个问题相对简单。不要遍历
ArrayList
s,而是遍历
List
s。e、 g.
for(列表l:getBatches(a)
。然后只需制作
getBatches()
return
ArrayList


一般来说,您需要尽可能使用最抽象的东西。如果您不需要
ArrayList
的特定于实现的详细信息,只需将其称为列表即可。

这是使用的结果

通过调用
new ArrayList(…)
而不指定
ArrayList
的泛型参数
T
,您使用的是原始类型
ArrayList

上面链接的文档说:

但如果将原始类型分配给参数化类型,则会得到 警告:

Eclipse显示以下与新ArrayList(Arrays.asList(optionId))相关的警告;

类型安全性:类型
ArrayList
的表达式需要取消选中 转换为符合
ArrayList

因此,将原始类型的
ArrayList
返回为
ArrayList
,不会导致编译时错误

getBatches(a)
的结果类型为
ArrayList
。此类型列表的元素类型为
ArrayList
。使用原始类型
ArrayList
将它们分配给
ax
,也没有编译时错误

为了向后兼容,将参数化类型指定给其原始 类型是允许的:


但是在运行时,当涉及到将
getBatches(a)
元素强制转换为
ArrayList
时,忽略警告会导致
ClassCastException
,因为运行时类型
LinkedList
无法强制转换为
ArrayList
(此时已删除泛型类型)。
private static ArrayList<ArrayList<Integer>> getBatches(List<Integer> optionIds) {
    return new ArrayList<>(Arrays.asList(new ArrayList<>(optionIds)));
}