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))
相关推荐
mqiqe1 分钟前
Python MySQL通过Binlog 获取变更记录 恢复数据
开发语言·python·mysql
AttackingLin3 分钟前
2024强网杯--babyheap house of apple2解法
linux·开发语言·python
少说多做34314 分钟前
Android 不同情况下使用 runOnUiThread
android·java
知兀14 分钟前
Java的方法、基本和引用数据类型
java·笔记·黑马程序员
蓝黑202037 分钟前
IntelliJ IDEA常用快捷键
java·ide·intellij-idea
Ysjt | 深38 分钟前
C++多线程编程入门教程(优质版)
java·开发语言·jvm·c++
ephemerals__44 分钟前
【c++丨STL】list模拟实现(附源码)
开发语言·c++·list
码农飞飞1 小时前
深入理解Rust的模式匹配
开发语言·后端·rust·模式匹配·解构·结构体和枚举
一个小坑货1 小时前
Rust 的简介
开发语言·后端·rust