《ArrayList原碼分析》一文中提到了“為什么removeRange(int fromIndex,int toIndex)是protected的?”
先給出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 }
這是被調用的removeRange方法,看到沒有,里面執行了l.removeRange(fromIndex+offset,toIndex+offset),知道l是誰嗎?l定義在SubList中,還記得嗲用SubList方法傳入的list嗎?還記得調用subList時傳入的this嗎?還記得大明湖畔的夏雨荷嗎?!!!跑題了~~~
至此將進入ArrayList的removeRange(int fromIndex,int toIndex)方法。繞了一個大彎終於通過調到了這個方法,可是又有一個疑問了:調用了subList了不是通過返回的List<E>調用了clear嗎?仔細觀察會發現其實傳到SubList構造方法中並被保存的一直是原來的ArrayList,所以調用removeRange的時候毫無疑問是對原先的List進行了處理!!!
在結合那段英文的解釋,為了避免冗余......所以沒對用戶開放,當然你可以繼承ArrayList編寫自己的List類來調用這個方法。
終於真相大白了哈哈哈哈哈。是的,真相永遠只有一個!