List<Integer> list1 = new ArrayList<>();
list1.add(1);
List<Integer> list2 = list1;
list1.add(2);
代碼執(zhí)行完畢之后,list2將包含整數1和2。
而以下代碼則是深拷貝:
List<Integer> list1 = new ArrayList<>();
list1.add(1);
List<Integer> list2 = new ArrayList<>(list1);
list1.add(2);
代碼執(zhí)行完畢之后,list2將只包含整數1,不包含整數2。
Immutable對象:上述情形如果遇到immutable對象,即不可變對象,其實是不需要深拷貝的(不僅不需要,還應該杜絕拷貝,因為純屬浪費)。但是前提是對象是真正的immutable。反面例子為:
public class NonStrictlyImmutable {
private final List<Integer> mList = new ArrayList<>();
public List<Integer> getList() {
return mList;
}
}
mList成員設置為了private final,NonStrictlyImmutable對象實例化完成后mList所引用的實際對象也不可再被改變,然而mList這個List的元素確是可以改變的,nonStrictlyImmutable.getList().add(1)并不會報編譯錯誤,而這一行代碼卻實實在在改變了nonStrictlyImmutable對象的值!
而如果getList()函數不直接返回mList引用,創(chuàng)建一個副本,或者使其不可被改變,則可以達到”嚴格意義上的“immutable。例如:
public class NonStrictlyImmutable {
private final List<Integer> mList = new ArrayList<>();
public List<Integer> getList() {
// 以下兩種方式都可以,各有優(yōu)劣
// return new ArrayList<>(mList);
// return Collections.unmodifiableList(mList);
return Collections.unmodifiableList(mList);
}
}
上面兩種方式各有優(yōu)劣:前者允許對新獲取到的副本進行修改操作而不會拋出異常,但會把底層數組數據創(chuàng)建多份;后者不會創(chuàng)建多份底層數組數據,但是如果對getList()返回的引用進行修改操作,將會拋出異常;見仁見智。