为什么阿里巴巴要求谨慎使用ArrayList中的subList方法
作者:网友投稿 时间:2019-06-26 21:11

集合是Java开发日常开发中经常会使用到的。在之前的一些文章中,我们介绍过一些关于使用集合类应该注意的事项,如《为什么阿里巴巴禁止在 foreach 循环里进行元素的 remove/add 操作》、《为什么阿里巴巴建议集合初始化时,指定集合容量大小》等。
关于集合类,《阿里巴巴Java开发手册》中其实还有另外一个规定:

本文就来分析一下为什么会有如此建议?其背后的原理是什么?
1.subList
subList是List接口中定义的一个方法,该方法主要用于返回一个集合中的一段、可以理解为截取一个集合中的部分元素,他的返回值也是一个List。
如以下代码:
public static void main(String[] args) {
List<String> names = new ArrayList<String>() {{
add("Hollis");
add("hollischuang");
add("H");
}};
List subList = names.subList(0, 1);
System.out.println(subList);
}
以上代码输出结果为:
[Hollis]
如果我们改动下代码,将subList的返回值强转成ArrayList试一下:
public static void main(String[] args) {
List<String> names = new ArrayList<String>() {{
add("Hollis");
add("hollischuang");
add("H");
}};
ArrayList subList = names.subList(0, 1);
System.out.println(subList);
}
以上代码将抛出异常:
java.lang.ClassCastException:
java.util.ArrayList$SubList cannot be cast to java.util.ArrayList
不只是强转成ArrayList会报错,强转成LinkedList、Vector等List的实现类同样也都会报错。
那么,为什么会发生这样的报错呢?我们接下来深入分析一下。
2.底层原理
首先,我们看下subList方法给我们返回的List到底是个什么东西,这一点在JDK源码中注释是这样说的:
Returns a view of the portion of this list between the specifiedfromIndex, inclusive, and toIndex, exclusive.
也就是说subList 返回是一个视图,那么什么叫做视图呢?
我们看下subList的源码:
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
这个方法返回了一个SubList,这个类是ArrayList中的一个内部类。
SubList这个类中单独定义了set、get、size、add、remove等方法。
当我们调用subList方法的时候,会通过调用SubList的构造函数创建一个SubList,那么看下这个构造函数做了哪些事情:
SubList(AbstractList<E> parent,


