java深複製和淺複製

來源:互聯網
上載者:User

複製就是複製一個對象的複本.但一個對象中可能有基礎資料型別 (Elementary Data Type),如:int,long,float    等,也同時含有非基礎資料型別 (Elementary Data Type)如(數組,集合等)
被複製得到的對象基本類型的值修改了,原對象的值不會改變.這種適合shadow clone(淺複製).

但如果你要改變一個非基本類型的值時,原對象的值卻改變了,.比如一個數組,記憶體中只copy他的地址,而這個地址指向的值並沒有copy,當clone時,兩個地址指向了一個值,這樣一旦這個值改變了,原來的值當然也變了,因為他們共用一個值.,這就必須得用深複製(deep clone)

以下舉個例子,說明以上情況:

被複製類:ShadowClone.java

class ShallowClone implements Cloneable {
    public int a;
    public int[] b;
    
    public ShallowClone() {
        a = 5;
        b = new int[] {1, 2, 3, 4, 5};
    }
    
    // 淺複製,對於複製後的對象,只能保證對基礎類型成員的修改不會影響原對象的相應成員
    // 對類類型和數群組類型的成員,只是拷貝了對象的地址,因此對複製後對象的這些類型成員
    // 進行修改會影響原對象
    @Override
    public Object clone() {
        ShallowClone sc = null;
        try {
            sc = (ShallowClone)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return sc;
    }
}

測試類別:

public class DeepAndShallowClone {
    public static void main(String[] args) throws Exception {
        // shallow clone
        ShallowClone sc = new ShallowClone();
        ShallowClone scCopy = (ShallowClone)sc.clone();
        
        
        System.out.println("Shallow Copy");
        System.out.println("--Before clone");
        System.out.println("sc.a=" + sc.a);
        System.out.println("sc.b=" + sc.b[0]);
        
        scCopy.a = 1;
        scCopy.b[0] = 10;
        System.out.println("--After clone");
        System.out.println("sc.a=" + sc.a);
        System.out.println("sc.b=" + sc.b[0]);
        System.out.println("scCopy.a=" + scCopy.a);
        System.out.println("scCopy.b=" + scCopy.b[0]);
    }
}

結果如下:

Shallow Copy
--Before clone
sc.a=5
sc.b=1
--After clone
sc.a=5
sc.b=10
scCopy.a=1
scCopy.b=10

問題出現了,修改了複製後的對象scCopy.b[0]的值,但sc.b[0]的值也改變了,與scCopy.b[0]的值相等.
以下針對淺複製得出結論:基本類型是可以被複製的,但參考型別只是copy地址,並沒有copy這個地址指向的對象的值,這使得兩個地址指向同一值,修改其中一個,當然另一個也就變了.
由此可見,淺複製只適合複製基本類型,對於參考型別就不能實現複製了.

那如何?複製引用對象呢,以下提供一種方法.    用序列化與還原序列化實現深複製(deep copy)

被複製對象.DeepClone.java

class DeepClone implements Serializable {
    private static final long serialVersionUID = 1L;
    public int a;
    public int[] b;
    
    public DeepClone() {
        a = 10;
        b = new int[] {6, 7, 8, 9, 10};
    }
    
    // 使用ObjectInput(Output)Stream和ByteArrayInput(Output)Stream實現深複製
    public Object deepClone() throws IOException, ClassNotFoundException {
        DeepClone dc = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(this);
        oos.close();
        
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream bis = new ObjectInputStream(bais);
        dc = (DeepClone)bis.readObject();
        return dc;
    }
}

  測試類別:

public class DeepAndShallowClone {
    public static void main(String[] args) throws Exception {
        DeepClone dc = new DeepClone();
        DeepClone dcCopy = (DeepClone)dc.deepClone();
        System.out.println("--Before clone");
        System.out.println("dc.a=" + dc.a);
        System.out.println("dc.b=" + dc.b[0]);
        dcCopy.a = 1;
        dcCopy.b[0] = 1;
        
        System.out.println("Shallow Copy");
        System.out.println("--After clone");
        System.out.println("dc.a=" + dc.a);
        System.out.println("dc.b=" + dc.b[0]);
        System.out.println("dcCopy.a=" + dcCopy.a);
        System.out.println("dcCopy.b=" + dcCopy.b[0]);
    }
}

  結果如下:

--Before clone
dc.a=10
dc.b=6
Shallow Copy
--After clone
dc.a=10
dc.b=6
dcCopy.a=1
dcCopy.b=1

writeObject方法會將被複製類的對象關係網都寫出,這樣就可以實現深複製。當然,每個被複製的成員類型必須實現Serializable介面

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.