浅拷贝和深拷贝的深度理解

本文深入探讨了Java中的浅拷贝和深拷贝概念,通过实例代码展示了两者的区别。浅拷贝创建的是对象引用的副本,而深拷贝则创建了对象内容的全新副本,确保修改时不互相影响。文章提供了具体的测试用例来说明这两种拷贝方式在处理引用类型属性时的行为差异,并给出了如何实现深拷贝的解决方案。
摘要由CSDN通过智能技术生成

前言

这道问题经常在面试题中遇到
甚至在leetcode算法也有体现
比如这两行代码的区别

res.add(new ArrayList<String>(item));
res.add(item);

学完这篇文章再来回顾一下这个知识点

1. 定义

深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用

  • 浅拷贝(shallowCopy):增加一个指针指向已存在的内存地址

  • 深拷贝(deepCopy):增加一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存

查看其概念,发现还是有些懵懂
通俗易懂的说:

A复制B,两者都是一样,但是修改B(原始状态)的时候,看A是否发生变化

  • 浅拷贝现象:A跟着也变了(拿人手短,原模原样复制),因为修改堆内存中的同一个值

  • 深拷贝现象:A没有改变(自食其力),因为修改堆内存中的不同的值,而且有了新地址

2. 浅拷贝

有着原始对象属性值的一份精确拷贝

  • 属性是基本类型,拷贝的就是基本类型的值
  • 属性是引用类型(内存地址),拷贝是内存地址(修改其地址,会影响到另一个对象调用其地址内的数据)

书写一个引用类的代码模块

@Data
@AllArgsConstructor
@NoArgsConstructor
public class books {

    private String name;

}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student  {

    //引用类型
    private books books;
    //基础数据类型
    private String name;
    private int age;
}

具体其测试的实现类如下

public static void main(String[] args) {

        studentA.setBooks(new books("码农研究僧"););
        
        studentA.setName("码农");
        studentA.setAge(15);
        Student studentB = studentA;
        
        studentB.setName("研究僧");
        studentB.setAge(18);
        
        Books books = studentB.getBooks();    
        subjectB.setName("码农研究僧");
        
        System.out.println("studentA:" + studentA.toString());
        System.out.println("studentB:" + studentB.toString());
    }
}

通过其输出结果可以发现
其地址都是一样的
也就是改变会连着一起改变数值

3. 深拷贝

深拷贝,在拷贝引用类型成员变量时,为引用类型的数据成员另辟了一个独立的内存空间,实现真正内容上的拷贝

只需修改上面这部分代码即可

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student implements Cloneable {

    //引用类型
    private books books;
    //基础数据类型
    private String name;
    private int age;

    /**
     *  重写clone()方法
     * @return
     */
    @Override
    public Object clone() {
        //深拷贝
        try {
            // 直接调用父类的clone()方法
            Student student = (Student) super.clone();
            student.books = (Books) books.clone();
            return student;
        } catch (CloneNotSupportedException e) {
            return null;
        }
    }


}

其测试类和上面如出一辙

public static void main(String[] args) {

        studentA.setBooks(new books("码农研究僧"););
        
        studentA.setName("码农");
        studentA.setAge(15);
        Student studentB = (Student) studentA.clone();
        
        studentB.setName("研究僧");
        studentB.setAge(18);
        
        Books books = studentB.getBooks();    
        subjectB.setName("码农研究僧");
        
        System.out.println("studentA:" + studentA.toString());
        System.out.println("studentB:" + studentB.toString());
    }
}

地址不会随着改变
因为有个新地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农研究僧

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值