浅谈Java中实现深拷贝的两种方式—clone() & Serialized

Java中实现对象拷贝通常有两种方式:浅拷贝和深拷贝。浅拷贝只复制原对象中所有基本数据类型的值和引用类型变量的地址,而深拷贝则是在堆中重新开辟空间,将原对象的所有属性都复制到新的对象中去,新的对象与原始对象没有任何关联。本文将讲解Java中实现深拷贝的两种方式:clone()和Serialized。

使用clone()方法实现深拷贝

Java中Object类提供了一个clone()方法,允许对象从内存中进行复制,并将复制后的新对象返回。注意,使用该方法进行克隆需要确保所复制的类实现了Cloneable接口,并重写了Object类中的clone()方法。否则,在调用clone()方法时,编译器将会抛出CloneNotSupportedException异常。

下面是一个示例代码:

public class Person implements Cloneable {
    private String name;
    private List<String> hobbies;

    public Person(String name, List<String> hobbies) {
        this.name = name;
        this.hobbies = hobbies;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        //浅拷贝
        Person copy = (Person) super.clone();
        //深拷贝
        copy.hobbies = new ArrayList<>(this.hobbies);
        return copy;
    }
}

上述代码中,Person类实现了Cloneable接口,并重写了clone()方法。在clone()方法中,使用super.clone()进行浅拷贝,再使用new创建新的List对象对hobbies进行深拷贝,确保返回的新对象与原始对象没有任何关联。

下面是一个使用clone()方法实现深拷贝的测试例子:

public class CloneTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        List<String> hobbies = new ArrayList<>();
        hobbies.add("coding");
        Person person1 = new Person("Tom", hobbies);
        Person person2 = (Person)person1.clone();
        System.out.println(person1 == person2); // false
        System.out.println(person1.getHobbies() == person2.getHobbies()); // false
    }
}

使用clone()方法进行深拷贝后,测试代码输出__false, false__,说明person1与person2是两个不同的对象,同时person2的hobbies属性也是一个新的List对象,与person1的hobbies属性没有任何关联。

使用Serialized实现深拷贝

Java中的Serialized机制能够将对象的状态保存到文件中,也可以在网络上将对象的状态传输给其他计算机。被Serialized处理过的对象能够进行深拷贝。

下面是一个示例代码:

public class Person implements Serializable {
    private String name;
    private List<String> hobbies;

    public Person(String name, List<String> hobbies) {
        this.name = name;
        this.hobbies = hobbies;
    }

    public List<String> getHobbies() {
        return hobbies;
    }

    public String getName() {
        return name;
    }

    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Object deepClone() throws IOException, ClassNotFoundException {
        // 复制到流中
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        // 从流中读回
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
    }
}

上述示例代码中,Person实现了Serializable接口,同时实现了一个deepClone()方法进行深拷贝。在deepClone()方法中,将对象复制到输出流中,再从输入流中读取并创建新的对象。使用该方法能够完全复制原始对象,确保返回的新对象与原始对象没有任何关联。但同时也需要注意,要求Person类中所有成员变量都是Serializable的。

下面是一个使用Serialized实现深拷贝的测试例子:

public class SerializedTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        List<String> hobbies = new ArrayList<>();
        hobbies.add("reading");
        Person person1 = new Person("Lucy", hobbies);
        Person person2 = (Person) person1.deepClone();
        System.out.println(person1 == person2); // false
        System.out.println(person1.getHobbies() == person2.getHobbies()); // false
    }
}

使用Serialized机制实现深拷贝后,测试代码输出__false, false__,说明person1与person2是两个不同的对象,同时person2的hobbies属性也是一个新的List对象,与person1的hobbies属性没有任何关联。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:浅谈Java中实现深拷贝的两种方式—clone() & Serialized - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 什么是标记-清除算法?

    以下是关于标记-清除算法的详细讲解: 什么是标记-清除算法? 标记-清除算法是一种常见的垃圾回收算法,它的原理是在程序运行过程中,标记所有不再使用的内存空间,然后清除这些内存空间,从而回收内存空间。标记清除算法分为两个阶段:标记阶段和清除阶段。 标记阶段 在标记阶段,垃圾回收器会遍历所有的对象,标记所有不再使用的对象。标记的方式通常是在对象头中添加一个标记位…

    Java 2023年5月12日
    00
  • Kafka 网络中断和网络分区4种场景分析

    Kafka 网络中断和网络分区 4 种场景分析 Kafka 是一个分布式消息系统,网络连接是其正常运行的必要条件。但是,在实践中,网络中断和网络分区可能会发生,这也是 Kafka 面临的常见问题之一。本文将介绍 Kafka 网络中断和网络分区的 4 种常见场景,并提供相关的解决方案。 1. 整个 Kafka 集群网络中断 在这种情况下,整个 Kafka 集群…

    Java 2023年5月20日
    00
  • Springboot apollo原理及使用方法详解

    SpringBootApollo原理及使用方法详解 1. 什么是SpringBootApollo SpringBootApollo是阿里巴巴开源的一款配置中心,它基于Apollo实现,并提供了SpringBoot的集成支持。使用SpringBootApollo,我们可以轻松地将Apollo配置中心集成到SpringBoot应用程序中,实现动态配置管理。 2.…

    Java 2023年5月15日
    00
  • idea快速搭建springboot项目的操作方法

    下面是“idea快速搭建springboot项目的操作方法”的完整攻略: 环境准备 首先,我们需要安装JDK和IntelliJ IDEA。 安装JDK:请前往Oracle官网下载 JDK 安装包,并按照官方向导安装。 安装IntelliJ IDEA:请前往JetBrains官网下载 IntelliJ IDEA 社区版,并按照官方向导安装。 创建项目 打开In…

    Java 2023年5月31日
    00
  • Extjs中通过Tree加载右侧TabPanel具体实现

    实现“Extjs中通过Tree加载右侧TabPanel”需要以下步骤: 创建一个Ext.tree.Panel,用于显示树形结构,其中需要配置store,root等属性。 示例代码: Ext.create(‘Ext.tree.Panel’, { store: yourTreeStore, root: { text: ‘Root’, expanded: true…

    Java 2023年6月15日
    00
  • GoLang与Java各自生成grpc代码流程介绍

    GoLang与Java都支持gRPC服务的生成,下面将详细介绍它们各自生成gRPC代码的流程: GoLang生成gRPC代码的流程 1.准备proto文件 准备好proto文件,它定义了gRPC服务所需要的消息结构和服务接口。 syntax = "proto3"; package greeter; message HelloRequest…

    Java 2023年5月26日
    00
  • JAVA中正则表达式小总结(整理)

    JAVA中正则表达式小总结(整理) 正则表达式的基本语法 正则表达式的语法分为两个部分,一个是元字符的语法,一个是限定符的语法。元字符代表一种类型的字符,在正则表达式中可以被用于匹配对应的字符,限定符用于限定匹配的次数。 元字符的语法 元字符 说明 . 匹配任意单个字符 \ 转义字符 [] 匹配中括号内的任意一个字符 [^] 匹配不在中括号内的任意一个字符 …

    Java 2023年5月27日
    00
  • Hibernate核心类和接口的详细介绍

    关于“Hibernate核心类和接口的详细介绍”的攻略如下: Hibernate 核心类和接口的详细介绍 SessionFactory SessionFactory 是 Hibernate 中最重要的类之一,用于创建 Session 对象。SessionFactory 是一个线程安全的、可被多个 Session 共用的对象。 SessionFactory 通…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部