clone常见的三种方式

在JAVA中克隆一个对象常见的有三种形式
1.通过自己写一个克隆方法里面 new 一个同样的对象来进行 get、set 依次赋值实现深度克隆(很繁琐且易出错);
2.通过实现 Cloneable 接口并重写 Object 类的 clone() 方法(分为深浅两种方式);
3.通过实现 Serializable 接口并用对象的序列化和反序列化来实现真正的深度克隆;

第一种方法并没有什么卵用

Cloneable 接口实现浅克隆

public class People implements Cloneable {

    private String name = "ilt";
    private Hand hand = new Hand();

    public Hand getHand() {
        return hand;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }
    public static void main(String[] args) throws CloneNotSupportedException {
        People p1 = new People();
        People p2 = (People) p1.clone();
        System.out.println("第一个对象的hash值:"+p1.hashCode());
        System.out.println("第二个对象的hash值:"+p2.hashCode());
        System.out.println("分割线-----------");
        System.out.println("p1中的hand对象的hash值:"+p1.getHand().hashCode());
        System.out.println("p2中的hand对象的hash值:"+p2.getHand().hashCode());
    }
}

class Hand implements Cloneable {

}

上面代码输出的结果如下,根据hash值相等能确定两个对象是否相等的原则,发现p1和p2不等,但p1中的hand对象与p2中的hand对象是相等的。Cloneable 接口实现克隆是先在内存中开辟一块和原始对象一样的空间,然后原样拷贝原始对象中的内容,对基本数据类型就是值复制,而对非基本类型变量保存的仅仅是对象的引用,所以会导致 clone 后的非基本类型变量和原始对象中相应的变量指向的是同一个对象。

第一个对象的hash值:1408448235
第二个对象的hash值:77244764
分割线-----------
p1中的hand对象的hash值:1172625760
p2中的hand对象的hash值:1172625760

Cloneable 接口实现深克隆

在浅度克隆的基础上对于要克隆对象中的非基本数据类型的属性对应的类也实现克隆,这样对于非基本数据类型的属性复制的不是一份引用。

public class People implements Cloneable {

    private String name = "ilt";
    private Hand hand = new Hand();

    public Hand getHand() {
        return hand;
    }

    public void setHand(Hand hand) {
        this.hand = hand;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        People p2 = (People) super.clone();
        p2.setHand((Hand) hand.clone());
        return p2;
    }
    public static void main(String[] args) throws CloneNotSupportedException {
        People p1 = new People();
        People p2 = (People) p1.clone();
        System.out.println("第一个对象的hash值:" + p1.hashCode());
        System.out.println("第二个对象的hash值:" + p2.hashCode());
        System.out.println("分割线-----------");
        System.out.println("p1中的hand对象的hash值:" + p1.getHand().hashCode());
        System.out.println("p2中的hand对象的hash值:" + p2.getHand().hashCode());
    }
}

class Hand implements Cloneable {

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }
}

结果如下,证明已经进行深克隆

第一个对象的hash值:1172625760
第二个对象的hash值:863719801
分割线-----------
p1中的hand对象的hash值:1696725334
p2中的hand对象的hash值:427340025

序列化与反序列化实现深克隆

对象序列化操作可以将对象的状态转换成字节流传输或者存储再生,我们可以借用这一特点实现对象的深度克隆,特别是当我们的对象嵌套非常复杂且想实现深度克隆时如果使用序列化方式会大大减少代码量。

public class TestClone implements Serializable{


    private static final long serialVersionUID = 1L;

    public String name = "ilt";


    public static void main(String[] args) throws Exception {
        TestClone t1 = new TestClone();
        byte[] b = ObjectUtil.objectToBytes(t1);//序列化
        TestClone t2 = (TestClone) ObjectUtil.bytesToObject(b);//反序列化
        System.out.println("t1对象的name:"+t1.name);
        System.out.println("t2对象的name:"+t2.name);
        System.out.println("分割线-------------");
        System.out.println("t1对象的hash值为:"+t1.hashCode());
        System.out.println("t2对象的hash值为:"+t2.hashCode());
        System.out.println("分割线-------------");
        System.out.println("t1中的obj对象的hash值为:"+t1.obj.hashCode());
        System.out.println("t2中的obj对象的hash值为:"+t2.obj.hashCode());

    }

    class Bean implements Serializable{

        private static final long serialVersionUID = 1L;

    }
}

结果如下`,证明对象的属性被深克隆下来了

t1对象的name:ilt
t2对象的name:ilt
分割线-------------
t1对象的hash值为:1847546936
t2对象的hash值为:812610706
分割线-------------
t1中的obj对象的hash值为:1164730192
t2中的obj对象的hash值为:1699624469
  • 9
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值