List.subList() 返回值为何不能直接转成 ArrayList?
摘要:先说结论 很多人用 subList() 的时候,可能会想当然地认为它返回的是一个新的 ArrayList。但实际上,subList() 返回的是原 List 的一个视图(View),并不是一个独立的 ArrayList 对象。这样会
先说结论
很多人用 subList() 的时候,可能会想当然地认为它返回的是一个新的 ArrayList。但实际上,subList() 返回的是原 List 的一个视图(View),并不是一个独立的 ArrayList 对象。
// 这样会报 ClassCastException
ArrayList<String> subArray = (ArrayList<String>) list.subList(0, 3); // 错误!
源码分析:subList 到底返回了什么?
我们先来看看 ArrayList 的 subList 方法源码:
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
可以看到,它返回的是一个 SubList 对象,这是 ArrayList 的私有内部类:
private class SubList extends AbstractList<E> implements RandomAccess {
private final AbstractList<E> parent;
private final int parentOffset;
private final int offset;
int size;
SubList(AbstractList<E> parent, int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}
public E get(int index) {
rangeCheck(index);
checkForComodification();
return ArrayList.this.elementData(offset + index);
}
public E set(int index, E e) {
rangeCheck(index);
checkForComodification();
E oldValue = ArrayList.this.elementData(offset + index);
ArrayList.this.elementData[offset + index] = e;
return oldValue;
}
}
关键点:
SubList 是 ArrayList 的私有内部类,继承 AbstractList,和 ArrayList 没有继承关系
它持有原 List 的引用(parent 字段)
它只记录了起始位置和长度(offset 和 size),没有复制数据
get/set 方法直接操作原 ArrayList 的底层数组 elementData
保存了创建时的 modCount,用于检测并发修改
所以 SubList 本质上就是一个视图,操作的是同一块内存区域。
基本用法
subList 方法签名:subList(fromIndex, toIndex),注意是左闭右开区间。
