先给出removeRange(int fromIndex,int toIndex)方法的源码(这段代码是干什么的就不再解释了,源码分析一文中已经说明)
1 protected void removeRange(int fromIndex, int toIndex) { 2 modCount++; 3 int numMoved = size - toIndex; 4 System.arraycopy(elementData, toIndex, elementData, fromIndex, 5 numMoved); 6 7 // Let gc do its work 8 int newSize = size - (toIndex-fromIndex); 9 while (size != newSize) 10 elementData[--size] = null; 11 }
可以看明白removeRange方法将制定范围内的元素都“删除”了,为什么这个方法不暴露给用户使用呢?
上网查了部分资料,靠谱一点的解释如下:http://stackoverflow.com/questions/2289183/why-is-javas-abstractlists-removerange-method-protected
再结合例子去验证,看一下代码及执行结果:
1 public static void main(String[] args) { 2 ArrayList<Integer> ints = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3 3, 4, 5, 6)); 4 // fromIndex low endpoint (inclusive) of the subList 5 // toIndex high endpoint (exclusive) of the subList 6 ints.subList(2, 4).clear(); 7 System.out.println(ints); 8 }
运行结果为:[0, 1, 4, 5, 6]
有没有发现这个结果就像是调用了removeRange(2,4)!这是怎么回事?接着看!
由于ArrayList并没有实现subList(int fromIndex,int toIndex)方法,所以调用的是父类的方法。看到父类AbstractList的subList方法:
1 public List<E> subList(int fromIndex, int toIndex) { 2 return (this instanceof RandomAccess ? 3 new RandomAccessSubList<E>(this, fromIndex, toIndex) : 4 new SubList<E>(this, fromIndex, toIndex)); 5 }
ArrayList实现了RandomAccess接口(可以看《ArrayList原码分析》),所以返回RandAccessSubList<E>(this,fromIndex,toIndex)。this、fromIndex、toIndex在上例中分别是ints、2、4。
下面是RandAccessSubList<E>(this,fromIndex,toIndex)的源码。
1 class RandomAccessSubList<E> extends SubList<E> implements RandomAccess { 2 RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) { 3 super(list, fromIndex, toIndex); 4 }
只是调用了父类的构造方法。下面给出被调用的构造方法。
1 SubList(AbstractList<E> list, int fromIndex, int toIndex) { 2 if (fromIndex < 0) 3 throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); 4 if (toIndex > list.size()) 5 throw new IndexOutOfBoundsException("toIndex = " + toIndex); 6 if (fromIndex > toIndex) 7 throw new IllegalArgumentException("fromIndex(" + fromIndex + 8 ") > toIndex(" + toIndex + ")"); 9 l = list; 10 offset = fromIndex; 11 size = toIndex - fromIndex; 12 expectedModCount = l.modCount; 13 }
至此subList方法调用结束。接着看clear()方法。由于subList方法返回的是List<E>所以该clear方法将调用AbstractList类的clear()方法。
1 public void clear() { 2 removeRange(0, size()); 3 }
终于看到removeRange了,看到希望了。
1 protected void removeRange(int fromIndex, int toIndex) { 2 checkForComodification(); 3 l.removeRange(fromIndex+offset, toIndex+offset); 4 expectedModCount = l.modCount; 5 size -= (toIndex-fromIndex); 6 modCount++; 7 }