深入JAVA对象深度克隆的详解

深入JAVA对象深度克隆的详解

对象深度克隆是指克隆一个对象及其子对象,同时新对象与原对象是互不干扰的,对新对象的任何修改都不会影响原对象。在Java中,实现对象深克隆通常使用“序列化”和“反序列化”技术。本篇文章将详细讲解如何实现Java对象的深度克隆。

实现Java对象深度克隆

方法一:序列化与反序列化实现克隆

序列化对象可以用ObjectOutputStream实现,创建一个ByteArrayOutputStream字节流,将对象写入字节流,再从字节流中读取对象信息并反序列化为原对象。

public static Object deepClone(Object obj) throws IOException, ClassNotFoundException {
    ObjectOutputStream oo = null;
    ObjectInputStream oi = null;
    try {
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        oo = new ObjectOutputStream(bo);
        oo.writeObject(obj);
        oi = new ObjectInputStream(new ByteArrayInputStream(bo.toByteArray()));
        return oi.readObject();
    } finally {
        if (oo != null) {
            oo.close();
        }
        if (oi != null) {
            oi.close();
        }
    }
}

方法二:递归实现克隆

定义一个方法,遍历对象及其子对象,并重构克隆对象,最终返回新的对象。

public static Object deepClone(Object obj) {
    if (obj == null) {
        return null;
    }
    Object result = null;
    try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(obj);
        oos.close();
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        result = ois.readObject();
        ois.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}

示例说明

下面我们通过一个示例说明深度克隆方法的使用:

public class Person implements Serializable {
    private String name;
    private Address address;

    public Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public Address getAddress() {
        return address;
    }
}

public class Address implements Serializable {
    private String province;
    private String city;

    public Address(String province, String city) {
        this.province = province;
        this.city = city;
    }

    public String getProvince() {
        return province;
    }

    public String getCity() {
        return city;
    }
}

public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Address address = new Address("广东省", "深圳市");
        Person person1 = new Person("小明", address);
        Person person2 = (Person) deepClone(person1);
        System.out.println(person1.getName() + "," + person1.getAddress().getProvince() + "," + person1.getAddress().getCity());
        System.out.println(person2.getName() + "," + person2.getAddress().getProvince() + "," + person2.getAddress().getCity());
        address.setCity("广州市");
        System.out.println(person1.getName() + "," + person1.getAddress().getProvince() + "," + person1.getAddress().getCity());
        System.out.println(person2.getName() + "," + person2.getAddress().getProvince() + "," + person2.getAddress().getCity());
    }

    public static Object deepClone(Object obj) throws IOException, ClassNotFoundException {
        ObjectOutputStream oo = null;
        ObjectInputStream oi = null;
        try {
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            oo = new ObjectOutputStream(bo);
            oo.writeObject(obj);
            oi = new ObjectInputStream(new ByteArrayInputStream(bo.toByteArray()));
            return oi.readObject();
        } finally {
            if (oo != null) {
                oo.close();
            }
            if (oi != null) {
                oi.close();
            }
        }
    }
}

以上示例代码中,我们定义了Person类和Address类,Person对象包含Address对象。deepClone方法实现序列化与反序列化以达到深度克隆的效果。在测试中,我们先克隆一个person1对象,并打印出person1和person2的地址信息,接着改变address的城市信息,并再次打印两个对象的地址信息。可以看到,address对象被改变,但person1和person2的地址信息保持不变,这说明克隆是成功的,深度克隆不会影响原对象。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入JAVA对象深度克隆的详解 - Python技术站

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

相关文章

  • 如何检查线程状态?

    以下是关于如何检查线程状态的完整使用攻略: 如何检查线程状态? 在 Java 中,可以使用 Thread 类的 getState() 方法来获取线程的状态。该方法返回一个 Thread.State 枚举类型的值,表示线程的状态。 示例一:使用 getState() 方法获取线程状态。可以使用以下代码实现: public class MyThread exte…

    Java 2023年5月12日
    00
  • Spring Boot 实例代码之通过接口安全退出

    下面我将详细讲解Spring Boot实例代码之通过接口安全退出的攻略。 1. 确认需求 在开始编写代码之前,需要确认需求。根据题目要求,我们需要编写一个接口,让用户可以通过接口安全退出系统。 2. 编写代码 2.1. 添加依赖 首先,在pom.xml文件中添加Spring Security的依赖: <dependency> <groupI…

    Java 2023年6月3日
    00
  • kaptcha验证码组件使用简介解析

    首先给出一份包含标题、正文内容和示例代码的markdown文本: Kaptcha验证码组件使用简介解析 Kaptcha是一款Java语言编写的验证码组件,可以非常方便地为Web应用添加验证码保护。它支持自定义验证码样式,包括验证码字符、字体、大小、颜色、背景等,同时还具备多语言支持、音频验证码功能以及代码简单等优点。 在下面的示例中,我们将详细讲解如何使用K…

    Java 2023年6月15日
    00
  • Springboot中@Value的使用详解

    Spring Boot中@Value的使用详解 在Spring Boot应用程序中,我们经常需要从配置文件中读取配置信息。@Value注解是Spring框架提供的一种方便的方式,用于将配置文件中的值注入到Java类中。本文将详细讲解Spring Boot中@Value的使用详解,并提供两个示例。 1. 基本用法 @Value注解可以用于将配置文件中的值注入到…

    Java 2023年5月15日
    00
  • IDEA解决maven包冲突easypoi NoClassDefFoundError的问题

    我将为您详细讲解如何解决IDEA中使用maven引入easypoi后出现NoClassDefFoundError的问题。 问题描述 当我们在使用IDEA开发时,使用Maven引入easypoi后,导入相关类时遇到“NoClassDefFoundError”异常报错。因为整个项目中可能会存在多个版本的jar包导致依赖冲突,从而导致该问题的出现。 解决方案 为了…

    Java 2023年5月20日
    00
  • Java Mybatis框架Dao层的实现与映射文件以及核心配置文件详解分析

    接下来是详细讲解“Java Mybatis框架Dao层的实现与映射文件以及核心配置文件详解分析”的完整攻略: 1. Mybatis框架简介 Mybatis框架是一款开源的持久化框架,它使得Java程序员可以轻松的访问关系型数据库,同时封装了JDBC操作,使得使用者无需关心具体的JDBC实现。 2. Dao层实现 Dao层即数据访问层,它负责与数据库进行数据交…

    Java 2023年5月20日
    00
  • java 实现回调代码实例

    Java 实现回调是一种常见的编程模式,它可以帮助我们解决很多传统的异步编程问题。本文将为你详细讲解 Java 实现回调的完整攻略,并提供两个实例说明。 什么是回调 回调是指一种可选择的机制,应用程序可以将函数或方法(回调函数)作为参数传递到另一个函数或方法中,该函数或方法会在后续或并行线程中调用传入的函数或方法,让其完成某些操作。 回调实现 Java 中实…

    Java 2023年5月18日
    00
  • 全面了解java异常

    全面了解 Java 异常 在 Java 编程中,异常是一个不可避免的问题。当程序出现异常时,如果没有妥善的处理,会导致程序的崩溃。因此,全面了解 Java 异常是非常必要的。 什么是 Java 异常 Java 异常是指在程序运行过程中出现的错误或意外情况。Java 异常分为两种:可查异常和非可查异常。 可查异常:Java 编译器会强制程序员在代码中进行处理或…

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