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

时间:2018-10-23 06:31:43

标签: 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);
    }

}

private static ArrayList<ArrayList<Integer>> getBatches(List<Integer> optionIds) {
        return new ArrayList(Arrays.asList(optionIds));
}

执行的结果是:

  

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

for循环中会出现异常。

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

3 个答案:

答案 0 :(得分:5)

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

如果您将方法更改为:

private static ArrayList<ArrayList<Integer>> getBatches(List<Integer> optionIds) {
    return new ArrayList<>(Arrays.asList(optionIds));
}

您将收到编译错误。

为避免编译和运行时错误,您需要将传递给方法的List转换为ArrayList

private static ArrayList<ArrayList<Integer>> getBatches(List<Integer> optionIds) {
    return new ArrayList<>(Arrays.asList(new ArrayList<>(optionIds)));
}

这将返回一个ArrayList,其单个元素是一个ArrayList,其中包含与传递给该方法的List相同的元素。

答案 1 :(得分:2)

getBatches()返回通用类型为ArrayList<Integer>的ArrayList。 Arrays.asList()的返回类型是一个List接口。为了从List到ArrayList进行隐式转换。问题是您不能直接将ArrayList强制转换为LinkedList。

解决此问题相对简单。而不是通过ArrayList进行迭代,而是通过List进行迭代。例如for(List l: getBatches(a)。然后只需使getBatches()返回ArrayList<List<Integer>>

通常,您会希望使用最抽象的东西。如果您不需要ArrayList的实现特定细节,只需将其称为列表即可。

答案 2 :(得分:0)

这是使用raw type的结果。

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

上面链接的文档说:

  

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

Eclipse显示与new ArrayList(Arrays.asList(optionIds));相关的以下警告:

  

类型安全:类型ArrayList的表达式无需检查   转换为符合ArrayList<ArrayList<Integer>>

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

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

  

为了向后兼容,请将参数化类型分配给其原始数据   允许的类型:

但是在运行时,由于运行时类型为{{1},因此将getBatches(a)的元素强制转换为ArrayList时,忽略警告会导致ClassCastException }无法强制转换为LinkedList(目前已经具有已删除的通用类型)。