深拷贝与浅拷贝

理解一波概念:

浅拷贝: 除了引用指向的对象(在堆上,而引用是在栈上)不被拷贝,其余都被拷贝

深拷贝:引用所指向的堆上对象也会被拷贝一份

在这里插入图片描述

代码演示:

1.浅拷贝

定义一个IDCard 类:

package top.forethought.javagrammer.clone;

public class IDCard {
    private String No;
    private String name;

    public IDCard(String no, String name) {
        No = no;
        this.name = name;
    }
... 省略getter/setter
   
}

定义一个People 类,内部包含一个对IDCard 类型对象的引用


// 据说:浅拷贝,只会拷贝对象内部属性,以及引用,但是不会拷贝引用所指向的对象
//   深拷贝:也会拷贝引用指向的对象
public class People implements Cloneable  {

    private IDCard idCard;

    @Override
    protected Object clone() {
       Object ob= null;
       try{
        ob=   super.clone();
       }catch ( CloneNotSupportedException e){
           e.printStackTrace();
       }


        return ob;
    }

    public People(IDCard idCard) {
        this.idCard = idCard;
    }
... 省略getter/setter
 
}

测试方法:

   public static void main(String[] args)  {
        IDCard card=new IDCard("1234","张三");
        People origin=new People(card);// origin 对象的成员属性是一个
        //指向 名字叫"张三" 的IDCard 类型的对象的 引用
        People clone=(People)origin.clone();// 克隆origin 对象,
        card.setName("李白");// 对引用指向的堆上对象做出修改
        // 如果是深拷贝,clone 对象的idcard 应该是不会发生改变的(因为深度拷贝,是将引用指向的堆上对象也拷贝了一个)
        System.out.println(clone.getIdCard().getName());

    }

测试结果:
在这里插入图片描述
观察测试结果:发现 origin,clone 中的idCard 所指向的堆上对象的属性name dou发生了改变
说明这是浅拷贝!!!

同时通过**{IDCard@524}** 也可以发现这三个地方出现的idCard 都是堆上的同一个对象
{类名@JVM中对象内存地址} 是Object 类的默认toString 方法实现

但是我们是想实现深度拷贝,而不是这样的浅拷贝,应为浅拷贝会导致无论哪一个对象修改,其他对象也会跟着修改,导致对象间不是独立的关系,这对实际业务会造成蜜汁bug

2深度拷贝实现:

IDCard


public class IDCard  implements Cloneable{
    private String No;
    private String name;

    public IDCard(String no, String name) {
        No = no;
        this.name = name;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    ... 省略getter/setter
    }

People

public class People implements Cloneable  {

    private IDCard idCard;

//    @Override
//    protected Object clone() {
//       Object ob= null;
//       try{
//        ob=   super.clone();
//       }catch ( CloneNotSupportedException e){
//           e.printStackTrace();
//       }
//
//
//        return ob;
//    }
@Override
   protected Object clone() {
    People obj=null;
    try{
        obj= (People) super.clone();
        obj.idCard= (IDCard) idCard.clone();//将引用指向的对象也拷贝一份
    }catch (CloneNotSupportedException e){
        e.printStackTrace();
    }
    return obj;

   }

    public People(IDCard idCard) {
        this.idCard = idCard;
    }

 ... 省略getter/setter
}

测试代码同浅拷贝测试,
测试效果:
在这里插入图片描述
现在发现,修改原来的堆上对象,不会影响到由拷贝产生的新的对象

总结:

注意对引用类型的处理上,浅拷贝,只处理自己这个类里面的数据,比如引用类型,但是不关心引用所指向的堆上对象是啥样

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值