深入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日

相关文章

  • 使用JWT作为Spring Security OAuth2的token存储问题

    使用JWT(JSON Web Token)作为 Spring Security OAuth2 的 token 存储方案,可以避免服务器端存储 token 所带来的开销和管理复杂度,并且具有无状态、分布式、可扩展、自包含等优点,在实际开发中非常实用。下面是一份完整攻略: 1. 引入相关依赖 在 pom.xml 中添加 spring-security-jwt 依…

    Java 2023年6月3日
    00
  • MyEclipse 配置SQL Server 2008数据库驱动操作步骤

    我们来详细讲解”MyEclipse配置SQL Server 2008数据库驱动操作步骤”的完整攻略。 确认MyEclipse版本和SQL Server版本 首先,需要确认你的MyEclipse版本和SQL Server版本。MyEclipse版本要求为10.x及以上,SQL Server版本要求为2008及以上。 下载SQL Server JDBC驱动 其次…

    Java 2023年6月16日
    00
  • Mybatis自动创建表和更新表结构

    下面给您详细讲解Mybatis自动创建表和更新表结构的完整攻略。 什么是Mybatis Mybatis是一种基于Java语言的开源持久化框架,它的主要功能是将Java对象映射到关系型数据库。 Mybatis自动创建表和更新表结构的配置方法 配置实体类 首先我们需要在实体类中添加注解,用来指定表名、字段名和主键。 下面是一个示例: public class U…

    Java 2023年5月20日
    00
  • Java深入讲解Object类常用方法的使用

    Java深入讲解Object类常用方法的使用攻略 介绍 在Java中,所有的类都默认继承自Object类,Object类是Java中非常重要的一个类。Object类中拥有很多方法,本攻略主要介绍Object类常用方法的使用。 常用方法列表 下面列举了Object类中的常用方法: equals(Object obj):判断对象是否相等。 toString():…

    Java 2023年5月26日
    00
  • eclipse创建springboot项目的三种方式总结

    在Eclipse中,我们可以使用以下三种方式来创建Spring Boot项目: 使用Spring Initializr创建项目 使用Eclipse自带的Spring Boot项目向导创建项目 使用Maven或Gradle创建项目 以下是每种方式的详细步骤和示例: 1. 使用Spring Initializr创建项目 步骤 打开Eclipse,选择File -…

    Java 2023年5月14日
    00
  • Java中的泛型方法详解及简单实例

    Java中的泛型方法详解及简单实例 什么是泛型方法? 泛型方法是具有参数化类型的方法。所谓参数化类型,即类型形参用作方法参数类型或返回类型。Java语言支持在类和接口中定义泛型方法,当然也可以在方法中定义泛型方法。 泛型方法简化了我们对一个类中泛型参数类型的定义,使得我们能够更容易地实现代码的复用。 泛型方法的定义 泛型方法定义的通用格式: 修饰符 <…

    Java 2023年5月26日
    00
  • Java(TM) Platform SE binary 打开jar文件的操作

    首先我们需要了解一下什么是Java(TM) Platform SE binary。它是Java平台标准版二进制文件的名称,也就是我们常说的JRE(Java Runtime Environment)。JRE是Java程序运行的环境,如果我们要打开.jar文件,则需要在拥有JRE的环境下进行操作。 下面是通过Java(TM) Platform SE binary…

    Java 2023年5月26日
    00
  • ajax jquery实现页面某一个div的刷新效果

    下面我就来详细讲解一下“ajax jquery实现页面某一个div的刷新效果”的完整攻略: 1. 理解 AJAX 在使用 AJAX 前,我们需要先理解什么是 AJAX。AJAX 全称是 Asynchronous JavaScript and XML,翻译过来是“异步 JavaScript 和 XML”。它是一种用于创建快速动态网页的技术,允许在不重新加载整个…

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