天天看點

深複制和淺複制

在設計模式中的prototype模式中,要特别留意的是其中的深複制和淺複制,現在小結一下

1 淺複制

   當進行淺複制時,如果類中包含了子對象,當這個類的包含的子引用對象發生改變時,這個變化會同時出現在它的淺複制克隆的對象中

去,比如

public class Lay1 implements Cloneable {

 public int x;

 public Lay2 lay2;

 public Object clone()

 {

  Object clone=null;

  try

  {

   clone=super.clone();

  }

  catch (CloneNotSupportedException e)

  return clone;

 }

}

Lay1中包含子對象lay2了,lay2指向一個類Lay2

public class Lay2 implements Cloneable {

 public int y;

   }

客戶程式

public class Client {

   public static  void main(String argv[])

   {

     Lay1 obj1=new Lay1();

     obj1.lay2=new Lay2();

     obj1.x=1;

     obj1.lay2.y=1;

     Lay1 obj2=(Lay1)obj1.clone();

     obj2.x=2;

     obj2.lay2.y=2;

     System.out.println("obj1.x is:"+obj1.x+"\tObj1.lay2.y is:"+obj1.lay2.y);

     System.out.println("obj2.x is:"+obj2.x+"\tObj2.lay2.y is:"+obj2.lay2.y);

   }

輸出為

obj1.x i s:1  obj1.lay2.y=2

obj2.x  is 2  obj2.lay2.y=

可以看到 obj1目前層的對象别clone了一份,但clone對象的值的改變不反映到父對象,但修改其引用的子對象lay2的值,會反映到父方,因為大家都是指向同一個地方嘛。

為了深複制,可以這樣做

   public int x;

   public Lay2 lay2;

   public Object clone() {

    Lay1 temp=null;

     try {

      temp=(Lay1)super.clone();

      temp.lay2=(Lay2)lay2.clone();

     }

     catch (CloneNotSupportedException e) {

       // should never happen

     return temp;

   public int y;

     Object clone = null;

       clone = super.clone ();

     return clone;

可以看到。輸出是

obj1.x is:1 Obj1.lay2.y is:1

obj2.x is:2 Obj2.lay2.y is:2

另外,給出C#版本的代碼,注意C#中淺複制用到的memberwiseclone()(轉自

javascript:void(0))

using System;

深複制和淺複制
深複制和淺複制

class ShallowCopy : ICloneable

深複制和淺複制
深複制和淺複制
深複制和淺複制

{

深複制和淺複制
深複制和淺複制

  public int[] v = 

深複制和淺複制

{1,2,3};

深複制和淺複制

  public Object Clone()

深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制

    return this.MemberwiseClone();

深複制和淺複制
深複制和淺複制
深複制和淺複制

  public void Display()

深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制

    foreach(int i in v)

深複制和淺複制

      Console.Write( i + ", ");

深複制和淺複制

    Console.WriteLine();

深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制

class Client

深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制

  public static void Main()

深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制

    ShallowCopy sc1 = new ShallowCopy();

深複制和淺複制

    ShallowCopy sc2 = (ShallowCopy)sc1.Clone();

深複制和淺複制

    sc1.v[0] = 9;

深複制和淺複制
深複制和淺複制

    sc1.Display();

深複制和淺複制

    sc2.Display();

深複制和淺複制
深複制和淺複制

ShallowCopy對象實作了一個淺拷貝,是以當對sc1進行克隆時,其字段v并沒有克隆,這導緻sc1與sc2的字段v都指向了同一個v,是以,當修改了sc1的v[0]後,sc2的v[0]也發生了變化。

深複制

深複制和淺複制
深複制和淺複制

class DeepCopy : ICloneable

深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制

  // 預設構造函數

深複制和淺複制

  public DeepCopy()

深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制

  // 供Clone方法調用的私有構造函數

深複制和淺複制

  private DeepCopy(int[] v)

深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制

    this.v = (int[])v.Clone();

深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制

    // 構造一個新的DeepCopy對象,構造參數為

深複制和淺複制

    // 原有對象中使用的 v 

深複制和淺複制

    return new DeepCopy(this.v);

深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制
深複制和淺複制

    DeepCopy dc1 = new DeepCopy();

深複制和淺複制

    DeepCopy dc2 = (DeepCopy)dc1.Clone();

深複制和淺複制

    dc1.v[0] = 9;

深複制和淺複制
深複制和淺複制

    dc1.Display();

深複制和淺複制

    dc2.Display();

深複制和淺複制
深複制和淺複制

這次在克隆的時候,不但克隆對象本身,連裡面的數組字段一并克隆。是以,最終列印出來的dc1與dc2不同。