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))
相关推荐
hengzhepa7 分钟前
ElasticSearch备考 -- Async search
大数据·学习·elasticsearch·搜索引擎·es
哎呦没21 分钟前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
Kalika0-038 分钟前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
_.Switch40 分钟前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
编程、小哥哥1 小时前
netty之Netty与SpringBoot整合
java·spring boot·spring
代码雕刻家1 小时前
课设实验-数据结构-单链表-文教文化用品品牌
c语言·开发语言·数据结构
一个闪现必杀技1 小时前
Python入门--函数
开发语言·python·青少年编程·pycharm
Fan_web1 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
龙图:会赢的1 小时前
[C语言]--编译和链接
c语言·开发语言
小小洋洋2 小时前
BLE MESH学习1-基于沁恒CH582学习
学习