java实现shallow clone(浅克隆)与深克隆(deep clone)

克隆就是复制一个对象的复本.但一个对象中可能有基本数据类型,如:int,long,float    等,也同时含有非基本数据类型如(数组,集合等)被克隆得到的对象基本类型的值修改了,原对象的值不会改变.这种适合shadow clone(浅克隆).
但如果你要改变一个非基本类型的值时,原对象的值却改变了,.比如一个数组,内存中只copy他的地址,而这个地址指向的值并没有 copy,当clone时,两个地址指向了一个值,这样一旦这个值改变了,原来的值当然也变了,因为他们共用一个值.,这就必须得用深克隆(deep clone)
以下举个例子,说明以上情况.
被克隆类:ShadowClone.java

 

public class ShadowClone implements Cloneable
{
    // 基本类型
    private int a;
    // 非基本类型
    private String b;
    // 非基本类型
    private int[] c;
    // 重写Object.clone()方法,并把protected改为public
    @Override
    public Object clone()
    {
        ShadowClone sc = null;
        try
        {
            sc = (ShadowClone) super.clone();
        } catch (CloneNotSupportedException e)
        {
            e.printStackTrace();
        }
        return sc;
    }
    public int getA()
    {
        return a;
    }
    public void setA(int a)
    {
        this.a = a;
    }
    public String getB()
    {
        return b;
    }
    public void setB(String b)
    {
        this.b = b;
    }
    public int[] getC()
    {
        return c;
    }
    public void setC(int[] c)
    {
        this.c = c;
    }
}
测试类Test.java
 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Test
{
    public static void main(String[] args) throws CloneNotSupportedException
    {
        Test t = new Test();
        DeepClone dc1 = new DeepClone();
        // 对dc1赋值
        dc1.setA(100);
        dc1.setB("clone1");
        dc1.setC(new int[] { 1000 });
        System.out.println("克隆前: dc1.a=" + dc1.getA());
        System.out.println("克隆前: dc1.b=" + dc1.getB());
        System.out.println("克隆前: dc1.c[0]=" + dc1.getC()[0]);
        System.out.println("-----------");
        DeepClone dc2 = (DeepClone) t.deepClone(dc1);
        // 对c2进行修改
        dc2.setA(50);
        dc2.setB("clone2");
        int[] a = dc2.getC();
        a[0] = 500;
        dc2.setC(a);
        System.out.println("克隆前: dc1.a=" + dc1.getA());
        System.out.println("克隆前: dc1.b=" + dc1.getB());
        System.out.println("克隆前: dc1.c[0]=" + dc1.getC()[0]);
        System.out.println("-----------");
        System.out.println("克隆后: dc2.a=" + dc2.getA());
        System.out.println("克隆后: dc2.b=" + dc2.getB());
        System.out.println("克隆后: dc2.c[0]=" + dc2.getC()[0]);
    }
    // 用序列化与反序列化实现深克隆
    public Object deepClone(Object src)
    {
        Object o = null;
        try
        {
            if (src != null)
            {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                oos.writeObject(src);
                oos.close();
                ByteArrayInputStream bais = new ByteArrayInputStream(baos
                        .toByteArray());
                ObjectInputStream ois = new ObjectInputStream(bais);
                o = ois.readObject();
                ois.close();
            }
        } catch (IOException e)
        {
            e.printStackTrace();
        } catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        return o;
    }
}
结果:
克隆前: dc1.a=100
克隆前: dc1.b=clone1
克隆前: dc1.c[0]=1000
-----------
克隆前: dc1.a=100
克隆前: dc1.b=clone1
克隆前: dc1.c[0]=1000
-----------
克隆后: dc2.a=50
克隆后: dc2.b=clone2
克隆后: dc2.c[0]=500
深克隆后:修改dc1或者dc2,无论是基本类型还是引用类型,他们的值都不会随着一方改变另一方也改变.

总结:

当克隆的对象只有基本类型,不含引用类型时,可以用浅克隆实现.     

当克隆的对象含有引用类型时,必须使用深克隆实现.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值