Java中深拷贝和浅拷贝详解学习

一、什么是深拷贝?什么是浅拷贝?

Java中深拷贝和浅拷贝都是与Java中对象的复制有关。Java 中的深拷贝和浅拷贝通常通过实现 Cloneable 接口并重写 clone() 方法来实现。

浅拷贝:

在浅拷贝中,只有对象的基本数据类型属性被复制,而对象的引用类型属性则只是被复制了引用。这意味着新对象和原对象共享引用类型对象。

深拷贝:

在深拷贝中,会递归地复制对象及其所有子对象(无论是基本数据类型还是引用对象),确保新对象与原始对象完全独立。

二、浅拷贝示例

java 复制代码
@Data
public class Teacher implements Cloneable{
    private String name;
    private int age;
    private School school;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public Teacher(String name, int age, School school) {
        this.name = name;
        this.age = age;
        this.school = school;
    }
}

@Data
@Accessors(chain = true)
public class Teacher implements Cloneable{
    private String name;
    private int age;
    private School school;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();      //浅拷贝
    }

    public Teacher(String name, int age, School school) {
        this.name = name;
        this.age = age;
        this.school = school;
    }
}

@Slf4j
public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        School school = new School("AAA School");
        Teacher teacher = new Teacher("Alice", 20, school);
        Teacher backTeacher = (Teacher) teacher.clone();

        backTeacher.setName("Tom");
        backTeacher.setAge(18);
        backTeacher.getSchool().setName("BBB School");

        //将对象序列化为json字符串进行日志打印
        String jsonTeacher = JSON.toJSONString(teacher);
        String jsonBackTeacher = backTeacher.toString();

        log.info("[Teacher] jsonTeacher name is : {}", jsonTeacher);
        log.info("[Teacher] jsonBackTeacher name is : {}", jsonBackTeacher);
    }
}

输出结果:

java 复制代码
15:46:02.300 [main] INFO com.example.demo.entity.Main - [Teacher] teacher name is : {"age":20,"name":"Alice","school":{"name":"BBB School"}}
15:46:02.303 [main] INFO com.example.demo.entity.Main - [Teacher] teacher name is : Teacher(name=Tom, age=18, school=School(name=BBB School))

可以看到浅拷贝后,基本的数据类型修改没有影响,而对于引用对象数据修改后,原对象和复制的对象会联动修改

三、深拷贝示例

java 复制代码
@Data
@Accessors(chain = true)
public class Teacher implements Cloneable{
    private String name;
    private int age;
    private School school;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Teacher cloneTeacher = (Teacher) super.clone();
        cloneTeacher.school = (School) school.clone(); //深拷贝School对象
        return cloneTeacher;
    }

    public Teacher(String name, int age, School school) {
        this.name = name;
        this.age = age;
        this.school = school;
    }
}

@Data
@Accessors(chain = true)
public class School implements Cloneable{
    private String name;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public School(String name) {
        this.name = name;
    }
}

@Slf4j
public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        School school = new School("AAA School");
        Teacher teacher = new Teacher("Alice", 20, school);
        Teacher backTeacher = (Teacher) teacher.clone();

        backTeacher.setName("Tom");
        backTeacher.setAge(18);
        backTeacher.getSchool().setName("BBB School");

        //将对象序列化为json字符串进行日志打印
        String jsonTeacher = JSON.toJSONString(teacher);
        String jsonBackTeacher = backTeacher.toString();

        log.info("[Teacher] jsonTeacher name is : {}", jsonTeacher);
        log.info("[Teacher] jsonBackTeacher name is : {}", jsonBackTeacher);
    }
}

输出结果:

java 复制代码
16:49:45.213 [main] INFO com.example.demo.entity.Main - [Teacher] jsonTeacher name is : {"age":20,"name":"Alice","school":{"name":"AAA School"}}
16:49:45.215 [main] INFO com.example.demo.entity.Main - [Teacher] jsonBackTeacher name is : Teacher(name=Tom, age=18, school=School(name=BBB School))

可以看到深拷贝后,原对象和拷贝后的对象无论是基本数据还是引用对象的数据都相互独立,互不影响。

四、项目中如何实现深拷贝

在项目中会借助fastjson库通过序列化+反序列化的方式实现对于复制对象的深拷贝

代码示例如下:

java 复制代码
@Slf4j
public class Main {
    /**
     * 借助fastjson库 通过序列化 + 反序列化的方式实现对象的深拷贝
     *
     * @param object
     * @param <T>
     * @return
     */
    public static <T> T deepCopy(T object) {
        String jsonString = JSON.toJSONString(object);
        return JSON.parseObject(jsonString, (Class<? extends T>) object.getClass());
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        School school = new School("AAA School");
        Teacher teacher = new Teacher("Alice", 20, school);
        //Teacher backTeacher = (Teacher) teacher.clone();
        Teacher backTeacher = deepCopy(teacher);

        backTeacher.setName("Tom");
        backTeacher.setAge(18);
        backTeacher.getSchool().setName("BBB School");

        //将对象序列化为json字符串进行日志打印
        String jsonTeacher = JSON.toJSONString(teacher);
        String jsonBackTeacher = backTeacher.toString();

        log.info("[Teacher] jsonTeacher name is : {}", jsonTeacher);
        log.info("[Teacher] jsonBackTeacher name is : {}", jsonBackTeacher);
    }
}

输出结果:

java 复制代码
17:27:21.649 [main] INFO com.example.demo.entity.Main - [Teacher] jsonTeacher name is : {"age":20,"name":"Alice","school":{"name":"AAA School"}}
17:27:21.653 [main] INFO com.example.demo.entity.Main - [Teacher] jsonBackTeacher name is : Teacher(name=Tom, age=18, school=School(name=BBB School))
相关推荐
invicinble13 分钟前
对tomcat的提供的功能与底层拓扑结构与实现机制的理解
java·tomcat
较真的菜鸟26 分钟前
使用ASM和agent监控属性变化
java
黎雁·泠崖33 分钟前
【魔法森林冒险】5/14 Allen类(三):任务进度与状态管理
java·开发语言
Gain_chance1 小时前
36-学习笔记尚硅谷数仓搭建-DWS层数据装载脚本
大数据·数据仓库·笔记·学习
2301_763472461 小时前
C++20概念(Concepts)入门指南
开发语言·c++·算法
XH华2 小时前
备战蓝桥杯,第九章:结构体和类
学习·蓝桥杯
TechWJ2 小时前
PyPTO编程范式深度解读:让NPU开发像写Python一样简单
开发语言·python·cann·pypto
qq_12498707532 小时前
基于SSM的动物保护系统的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·毕业设计·ssm·计算机毕业设计
Coder_Boy_2 小时前
基于SpringAI的在线考试系统-考试系统开发流程案例
java·数据库·人工智能·spring boot·后端
Mr_sun.2 小时前
Day06——权限认证-项目集成
java