0
点赞
收藏
分享

微信扫一扫

深复制和浅复制


在设计模式中的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 Object clone()
{
Object clone=null;
try
{
clone=super.clone();
}
catch (CloneNotSupportedException e)
{

}
return clone;
}}

客户程序

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 class Lay1 implements Cloneable {
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 class Lay2 implements Cloneable {
public int y;
public Object clone() {
Object clone = null;
try {
clone = super.clone ();
}
catch (CloneNotSupportedException e) {
// should never happen
}
return clone;
}
}

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 is:1 Obj1.lay2.y is:1

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


另外,给出C#版本的代码,注意C#中浅复制用到的memberwiseclone()


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]也发生了变化。

深复制

using System;

class DeepCopy : ICloneable
{
public int[] v =
{1,2,3};

// 默认构造函数
public DeepCopy()

{
}

// 供Clone方法调用的私有构造函数
private DeepCopy(int[] v)

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

public Object Clone()

{
// 构造一个新的DeepCopy对象,构造参数为
// 原有对象中使用的 v
return new DeepCopy(this.v);
}

public void Display()

{
foreach(int i in v)
Console.Write( i + ", ");
Console.WriteLine();
}
}

class Client
{
public static void Main()

{
DeepCopy dc1 = new DeepCopy();
DeepCopy dc2 = (DeepCopy)dc1.Clone();
dc1.v[0] = 9;

dc1.Display();
dc2.Display();
}
}

这次在克隆的时候,不但克隆对象本身,连里面的数组字段一并克隆。因此,最终打印出来的dc1与dc2不同。

举报

相关推荐

0 条评论