Clone
Cloneable
接口
如果直接把一個變量賦給另一個變量,例如下面這句,e1,e2將指向同一個引用對象,如果改變e2的值,e1的值同樣將被改變。
Employee e2 = e1;
因此,爲了使e1,e2可以各自改變狀態,需要使用clone方法。clone()完全創造出一個新的對象,有自己的新的地址,只不過初始信息是和原對象是一樣的。
public Employee clone() throws CloneNotSupportedException
{
// call Object.clone()
Employee cloned = (Employee) super.clone();
// clone mutable fields
cloned.hireDay = (Date) hireDay.clone();
return cloned;
}
Cloneable接口是空的,不包括任何常量和抽象方法。實現Cloneable接口的類標記爲可克隆的,這個類必須覆蓋在Object類中定義的clone( )方法。
Object中的源碼:
protected native Object clone() throws CloneNotSupportedException;
淺拷貝
如果對象中的所有數據域都是數值或基本類型,使用clone拷貝域沒有任何問題。但如果在對象中包含了子對象的引用,clone不會拷貝子對象,只是把兩個域引用同一個子對象。
比如說,我們上面說到的Employee,它有一個string域、一個Date域。String域不允許改變的類,拷貝不會出錯。但Date類是可變的子對象,直接拷貝會出錯!因此必須重新定義clone方法
對每一個類,我們要先做出以下判斷:
- 默認的clone方法是否滿足要求
- 默認的clone方法是否能夠通過調用可變子對象的clone得到修補。
- 是否不應該使用clone
深拷貝
深拷貝和淺拷貝正好相反,在克隆一個對象時,其內的引用也發生了相應的克隆,都會產生完全沒有關聯的對象。即在對象中包含了子對象的引用,clone也會拷貝子對象。
public EmployeeForClone clone() throws CloneNotSupportedException
{
// call Object.clone()
EmployeeForClone cloned = (EmployeeForClone) super.clone();
// clone mutable fields
cloned.hireDay = (Date) hireDay.clone();
return cloned;
}
hireDay就是我們上邊說的Date對象,重新修改代碼後實現了深拷貝。
只要在clone中含有沒有實現Cloneable接口的對象,Object類的clone方法就會拋出一個CloneNot-SupportException
異常。因此需要聲明 ... throws CloneNotSupportedException