今天發(fā)現(xiàn)單獨的將一個ArrayList的對象添加到另外一個ArrayList的時候,總是源列表和目的列表相同的內存地址。原因如下:
偶然看到了Collections的copy(List desc,List src)方法.當時就想這個方法和初始化一個List desc=new ArrayList(List c)【參數必須實現(xiàn)Collection接口】的區(qū)別。
兩者的差別很大,后者是一個淺拷貝,只是對源list的元素進行拷貝,拷貝的只是引用。拷貝后兩個list的元素(引用)不同,但是引用所指向的對象是一樣的。即是兩個list的每個元素指向的還是通一內存。然而前者是深拷貝,不光拷貝的是src的元素(引用),src內每個元素的所指向的對象都進行一次拷貝。即是兩個list的每個元素所指向的不是同一內存。
所以使用了Collections.copy()方法來進行拷貝,但是這樣就接觸到了此方法所報出的異常:
使用后者進行拷貝的結果是:當你的desc鏈表發(fā)生改變時,src也將會隨之改變。
使用前者進行拷貝時你又必須要注意目標鏈表的長度必須要比源鏈表的長度大或者相等。
舉例如下:
List src1=new ArrayList(3)
src1.add("a");
src2.add("b");
src3.add("c");
如果你使用下面方法copy鏈表
/*******************************/
List des1=new ArrayList(3);
Collections.copy(des1,src1);
/*******************************/
將會出錯,拋出數組越界異常。
當時我怎么想都想不明白為什么,明明已經設置了長度為3,為什么還會出錯!
后來打印出des1.size()才知道des1的長度為0;3表示的是這個List的容納能力為3,并不是說des1中就有了3個元素。查看api才知道,它的capacity(容納能力大小)可以指定(最好指定)。而初始化時size的大小永遠默認為0,只有在進行add和remove等相關操作時,size的大小才變化。然而進行copy()時候,首先做的是將desc1的size和src1的size大小進行比較,只有當desc1的size 大于或者等于src1的size時才進行拷貝,否則拋出IndexOutOfBoundsException異常。
所以可以通過下面的方法指定目標desc的大小
/*******************************/
List des1=new ArrayList(Array.asList(new object[src1.size]));//注意:new ArrayList(Collection col)參數必須要實現(xiàn)Collection 接口。
Collections.copy(des1,src1);
/*******************************/
執(zhí)行第一句后size的大小是3,其實它是對一個空數組的淺拷貝。
使用這位仁兄的方法,我這邊一直報錯說找不到此構造函數,估計是因為我使用了jdk6的原因,后來使用了替代方法,用apache的CollectionUtils:
dest1 = new ArrayList();
CollectionUtils.addAll(dest1, new Object[src1.size()]);
Collections.copy(dest1, src1);