List<Integer> list1 = new ArrayList<>();
list1.add(1);
List<Integer> list2 = list1;
list1.add(2);
代碼執(zhí)行完畢之后,list2將包含整數(shù)1和2。
而以下代碼則是深拷貝:
List<Integer> list1 = new ArrayList<>();
list1.add(1);
List<Integer> list2 = new ArrayList<>(list1);
list1.add(2);
代碼執(zhí)行完畢之后,list2將只包含整數(shù)1,不包含整數(shù)2。
Immutable對象:上述情形如果遇到immutable對象,即不可變對象,其實(shí)是不需要深拷貝的(不僅不需要,還應(yīng)該杜絕拷貝,因?yàn)榧儗倮速M(fèi))。但是前提是對象是真正的immutable。反面例子為:
public class NonStrictlyImmutable {
private final List<Integer> mList = new ArrayList<>();
public List<Integer> getList() {
return mList;
}
}
mList成員設(shè)置為了private final
,NonStrictlyImmutable對象實(shí)例化完成后mList所引用的實(shí)際對象也不可再被改變,然而mList這個(gè)List的元素確是可以改變的,nonStrictlyImmutable.getList().add(1)
并不會報(bào)編譯錯(cuò)誤,而這一行代碼卻實(shí)實(shí)在在改變了nonStrictlyImmutable對象的值!
而如果getList()
函數(shù)不直接返回mList
引用,創(chuàng)建一個(gè)副本,或者使其不可被改變,則可以達(dá)到”嚴(yán)格意義上的“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)劣:前者允許對新獲取到的副本進(jìn)行修改操作而不會拋出異常,但會把底層數(shù)組數(shù)據(jù)創(chuàng)建多份;后者不會創(chuàng)建多份底層數(shù)組數(shù)據(jù),但是如果對getList()
返回的引用進(jìn)行修改操作,將會拋出異常;見仁見智。