如何将二维ArrayList传递给接收二维List的函数?
解决二维ArrayList转二维List的类型不兼容问题
这个问题本质是Java泛型的类型安全约束导致的,咱们先搞清楚原因,再给你可行的解决方案(完全不用修改fn1的方法签名哦)。
为什么会报错?
Java的泛型默认是不协变的——虽然ArrayList是List的子类,但ArrayList<ArrayList<Integer>>并不是List<List<Integer>>的子类。
举个简单的例子:如果允许这种转换,那在fn1里就可以执行x.add(new LinkedList<Integer>()),但原来的aList是ArrayList<ArrayList<Integer>>,它只能存储ArrayList<Integer>类型的元素,这样就会破坏类型安全。编译器正是为了避免这种情况,才抛出了类型不兼容的错误。
解决方案(不用修改fn1)
方案1:初始化时就声明正确的类型(最推荐)
直接把aList的声明类型改成List<List<Integer>>,初始化时用ArrayList实现类就行。这样后续添加的ArrayList<Integer>会自动向上转型为List<Integer>,完美匹配fn1的参数要求:
public class Main { static void fn1(List<List<Integer>> x){ System.out.println(x); } public static void main(String[] args) { // 直接声明为List<List<Integer>>,而不是ArrayList<ArrayList<Integer>> List<List<Integer>> aList = new ArrayList<>(); ArrayList<Integer> a1 = new ArrayList<>(); a1.add(1); a1.add(2); aList.add(a1); // 自动转型为List<Integer> ArrayList<Integer> a2 = new ArrayList<>(); a2.add(5); aList.add(a2); ArrayList<Integer> a3 = new ArrayList<>(); a3.add(10); a3.add(20); a3.add(30); aList.add(a3); // 原有的遍历代码完全不变 for (int i = 0; i < aList.size(); i++) { for (int j = 0; j < aList.get(i).size(); j++) { System.out.print(aList.get(i).get(j) + " "); } System.out.println(); } fn1(aList); // 现在可以正常调用,没有类型错误 } }
方案2:如果已经有了ArrayList<ArrayList>对象,转换后再传递
要是你因为某些原因不能修改aList的声明类型,可以把它转换成List<List<Integer>>再传给fn1:
// Java 9+ 可用List.copyOf(),生成不可变列表 fn1(List.copyOf(aList)); // 或者用Stream转换(Java 8+),生成可变列表 import java.util.stream.Collectors; fn1(aList.stream() .map(list -> (List<Integer>) list) .collect(Collectors.toList()));
验证效果
修改后运行代码,会先输出遍历的结果:
1 2 5 10 20 30
然后fn1会输出二维列表的内容:[[1, 2], [5], [10, 20, 30]],完全符合预期。
内容的提问来源于stack exchange,提问作者Devender Goyal
相关产品推荐
相关产品推荐

