clone(); 深拷貝、淺拷貝

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方法

對每一個類,我們要先做出以下判斷:

  1. 默認的clone方法是否滿足要求
  2. 默認的clone方法是否能夠通過調用可變子對象的clone得到修補。
  3. 是否不應該使用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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章