天天看点

深复制和浅复制

在设计模式中的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不同。