一文深入理解Java中的深拷贝机制

 更新时间:2023年09月04日 11:44:45   作者:峥嵘岁月702  
在Java编程中,我们经常需要处理对象的复制问题,深拷贝和浅拷贝是两种常见的复制方式,它们在内存管理和对象引用方面存在不同特点,本文将带大家深入探究Java中的深拷贝机制,需要的朋友可以参考下

一、深拷贝和浅拷贝的概念

深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是指在进行对象复制时所产生的两种不同结果。

  • 浅拷贝:浅拷贝是指创建一个新对象,然后将原始对象的非静态字段的值复制到新对象。新对象和原始对象共享引用类型的成员变量。简而言之,浅拷贝只复制对象的引用,而不复制引用指向的内容。

  • 深拷贝:深拷贝是指创建一个新对象,然后递归地复制原始对象的所有成员变量,包括引用类型的成员变量和基本类型的成员变量。深拷贝得到的新对象与原始对象完全独立,修改新对象不会影响原始对象。

接下来,我们将介绍三种常见的实现深拷贝的方法。

二、使用Cloneable接口与重写clone()方法

Java中的Object类提供了一个名为clone()的方法,用于实现对象拷贝。为了使用该方法进行深拷贝,需要满足两个条件:

  • 类实现Cloneable接口,将其标记为可以拷贝的。
  • 重写clone()方法,在方法中通过递归调用clone()来复制对象引用。

示例代码如下:

public class MyClass implements Cloneable {
    private int number;
    private List<String> list;
    MyClass() {
        this.number = 0;
        this.list = new ArrayList<>();
    }
    MyClass(int number) {
        this.number = number;
        this.list = new ArrayList<>();
    }
    void setNumber(int number) {
        this.number = number;
    }
    int getNumber() {
        return number;
    }
    @Override
    public MyClass clone() throws CloneNotSupportedException {
        MyClass copy = (MyClass) super.clone();
        copy.list = new ArrayList<>(this.list); // 进行深拷贝
        return copy;
    }
}
public class Main{
    public static void main(String[] args) throws CloneNotSupportedException {
        MyClass myClass1 = new MyClass(3);
        MyClass myClass2 = myClass1.clone();
        myClass1.setNumber(2);
        System.out.println(myClass2.getNumber()); // 3
    }
}

三、使用序列化与反序列化

Java中的序列化(Serialization)机制可以将一个对象转换为字节流,而反序列化(Deserialization)则可以将字节流还原为对象。利用这一机制,我们可以实现深拷贝。

示例代码如下:

public class MyClass implements Serializable {
    private int number;
    private List<String> list;
    MyClass() {
        this.number = 0;
        this.list = new ArrayList<>();
    }
    MyClass(int number) {
        this.number = number;
        this.list = new ArrayList<>();
    }
    void setNumber(int number) {
        this.number = number;
    }
    int getNumber() {
        return number;
    }
    public MyClass deepCopy() {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (MyClass) ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
public class Main{
    public static void main(String[] args) throws CloneNotSupportedException {
        MyClass myClass1 = new MyClass(3);
        MyClass myClass2 = myClass1.deepCopy();
        myClass1.setNumber(2);
        System.out.println(myClass2.getNumber()); // 3
    }
}

四、使用第三方库

除了自己手动实现深拷贝外,还可以使用一些优秀的第三方库来简化深拷贝的过程。例如,Apache Commons和Google Guava等库都提供了一些工具方法来实现深拷贝。

五、总结

深拷贝和浅拷贝在Java中是常见的操作,深拷贝复制对象以及其引用的所有子对象,而浅拷贝只复制对象本身。根据具体的需求和场景选择使用深拷贝还是浅拷贝非常重要,熟练掌握深拷贝和浅拷贝的概念和实现方法,对编写高效、安全的Java代码具有重要意义。

到此这篇关于一文深入理解Java中的深拷贝机制的文章就介绍到这了,更多相关Java深拷贝机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解JDK9特性之JPMS模块化

    详解JDK9特性之JPMS模块化

    JDK9引入了一个特性叫做JPMS(Java Platform Module System),也可以叫做Project Jigsaw。模块化的本质就是将一个大型的项目拆分成为一个一个的模块,每个模块都是独立的单元,并且不同的模块之间可以互相引用和调用。本文将详细介绍JDK9特性之JPMS模块化。
    2021-06-06
  • SpringBoot默认包扫描机制及@ComponentScan指定扫描路径详解

    SpringBoot默认包扫描机制及@ComponentScan指定扫描路径详解

    这篇文章主要介绍了SpringBoot默认包扫描机制及@ComponentScan指定扫描路径详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Spring security实现对账户进行加密

    Spring security实现对账户进行加密

    这篇文章主要介绍了Spring security实现对账户进行加密,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • TransmittableThreadLocal线程间传递逻辑示例解析

    TransmittableThreadLocal线程间传递逻辑示例解析

    这篇文章主要介绍了TransmittableThreadLocal线程间传递逻辑示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • Java中SPI机制的实现详解

    Java中SPI机制的实现详解

    SPI(Service Provider Interface),是 JDK 内置的一种服务提供发现机制,可以用来启用框架扩展和替换组件,下面我们就来看看Java中SPI机制的具体实现
    2024-01-01
  • 浅谈java socket的正确关闭姿势

    浅谈java socket的正确关闭姿势

    这篇文章主要介绍了java socket的正确关闭姿势,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • 分布式医疗挂号系统EasyExcel导入导出数据字典的使用

    分布式医疗挂号系统EasyExcel导入导出数据字典的使用

    这篇文章主要为大家介绍了分布式医疗挂号系统EasyExcel导入导出数据字典的使用,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • 从Java的jar文件中读取数据的方法

    从Java的jar文件中读取数据的方法

    这篇文章主要介绍了从Java的jar文件中读取数据的方法,实例分析了java档案文件的相关操作技巧,需要的朋友可以参考下
    2015-06-06
  • Maven默认使用JDK1.5的问题及解决方案

    Maven默认使用JDK1.5的问题及解决方案

    这篇文章主要介绍了Maven默认使用JDK1.5的问题及解决方案,本文给大家分享两种方式,通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • SpringBoot+@EnableScheduling使用定时器的常见案例

    SpringBoot+@EnableScheduling使用定时器的常见案例

    项目开发中经常需要执行一些定时任务,本文主要介绍了SpringBoot+@EnableScheduling使用定时器的常见案例,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09

最新评论