浅谈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日

相关文章

  • Mybatis面试题整理小结

    作为”Mybatis面试题整理小结”的作者,我将为你详细讲解如何攻略这份题目。整个攻略分为以下几个步骤: 步骤一:了解Mybatis的基础知识 首先,Mybatis是一款优秀的持久层框架,它基于Java语言,可以灵活地操作关系型数据库。在学习Mybatis之前,我们需要掌握一些基础知识,例如SQL语句的使用、Java对象映射等。如果你对这些知识还不太熟悉,建…

    Java 2023年5月20日
    00
  • Java实现读取及生成Excel文件的方法

    生成Excel文件可以使用Apache POI库,读取Excel文件可以使用JXL或者Apache POI库。 使用Apache POI进行Excel文件读取及生成 要使用Apache POI进行Excel文件处理,需要添加以下maven依赖: <dependency> <groupId>org.apache.poi</grou…

    Java 2023年5月20日
    00
  • 什么是类加载器委托机制?

    以下是关于类加载器委托机制的完整使用攻略: 什么是类加载器委托机制? 类加载器委托机制是Java虚拟机(JVM)用来加载类的一种机制。当J需要加载一个类时,它会先委托给父类加载器进行加载,如果父类加载器无法加载该类,则会委托给子类加载进行加载。这个过程会一直持续到顶层的父类加载器,如果顶层的父类加载器无法加载该类,则会抛ClassNotFoundExcept…

    Java 2023年5月12日
    00
  • java实现登录窗口

    下面就是Java实现登录窗口的攻略: 1. 准备工作 在Java中实现登录窗口,首先要准备以下几项工作: Java开发环境,如JDK或者集成开发环境(IDE); Swing类库,它是Java中的图形用户界面(GUI)工具包,用于构建界面组件; 了解Java的事件机制,因为登录窗口需要监听用户的操作。 2. 创建登录窗口 要创建一个登录窗口,需要用到Java中…

    Java 2023年5月19日
    00
  • Java Apache POI报错“InvalidFormatException”的原因与解决办法

    “IndexOutOfBoundsException”是Java的Apache POI类库中的一个异常,通常由以下原因之一引起: 索引错误:如果索引不正确,则可能会出现此异常。例如,可能会尝试访问不存在的行或列。 以下是两个实例: 例1 如果索引不正确,则可以尝试使用正确的索引以解决此问题。例如,在Java中,可以使用以下代码: FileInputStrea…

    Java 2023年5月5日
    00
  • Struts 2 配置Action详解

    Struts 2 配置Action详解 在 Struts 2 中,Action 是一个处理请求的对象,负责接收来自用户的请求,并进行处理。配置 Action 是 Struts 2 中比较重要的一项任务,配置不当会导致程序无法正常工作或者存在安全隐患。本篇文章将详细讲解 Struts 2 中如何配置 Action。 配置 Struts 2 Action 在 S…

    Java 2023年5月20日
    00
  • Java中间消息件ActiveMQ使用实例

    下面我来详细地讲解一下“Java中间消息件ActiveMQ使用实例”的完整攻略。 什么是ActiveMQ ActiveMQ是Apache下的一个开源项目,它实现了JMS规范,提供了消息收发的功能。ActiveMQ支持多种协议,包括TCP, SSL, NIO, UDP等等,因此可以很容易地集成到各种不同的应用中。 ActiveMQ的安装和配置 ActiveMQ…

    Java 2023年5月20日
    00
  • 如何使用Java编译期注解?

    下面是关于“如何使用Java编译期注解”的完整使用攻略。 什么是编译期注解? 编译期注解是在Java编译期间处理的一种注解,它可以被编译器直接解释和处理。编译器可以识别和处理这些注解,并在编译期执行相应的操作。相比于运行时注解,编译期注解更加高效、可靠和安全。 如何使用Java编译期注解? 使用Java编译期注解需要按照以下步骤进行: 1. 定义注解类 首先…

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