Java实现深拷贝的方式

news2024/11/25 16:46:06

文章目录

    • 1. 实现 Cloneable 接口并重写 clone() 方法
    • 2. 使用序列化和反序列化实现深拷贝
    • 3. 第三方工具
      • (1) Apache Commons BeanUtils 库
      • (2) Apache Commons Lang 库
      • (3) Spring Framework
      • (4) Kryo 序列化库
      • (5) FST 序列化库

1. 实现 Cloneable 接口并重写 clone() 方法

在 Java 中,实现深拷贝的一种方式是实现 Cloneable 接口并重写 clone() 方法。深拷贝是指在拷贝对象时,不仅拷贝对象本身,还要递归地拷贝其所有引用对象,以确保原始对象和拷贝对象的属性引用不同的对象实例。

public class jvmtestMain {
    public static void main(String[] args) throws  CloneNotSupportedException {
        Address a=new Address("北京");
        Address b= (Address) a.clone();
        System.out.println(b.getCity());
        System.out.println("a,b是否指向同一个对象:"+a.equals(b));
    }
}
class Address implements Cloneable {
    private String city;

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

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

在这里插入图片描述

2. 使用序列化和反序列化实现深拷贝

序列化是将对象转换为字节流的过程,以便可以将其保存到磁盘文件、通过网络传输或在内存中保存。序列化将对象的状态以二进制形式编码,以便稍后可以重新创建对象,这个过程称为反序列化。序列化在 Java 中有许多应用,其中之一是实现深拷贝。

public class jvmtestMain {
    public static <T> T deepClone(T obj) throws IOException, ClassNotFoundException {
        //序列化
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);
        out.writeObject(obj);
        out.close();

        //反序列化
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream in = new ObjectInputStream(bis);
        T clone = (T) in.readObject();
        in.close();

        return clone;
    }

    public static void main(String[] args) {
        Address originalAddress = new Address("New York");
        Person originalPerson = new Person("Alice", originalAddress);

        try {
            // Perform deep clone using serialization
            Person clonedPerson = deepClone(originalPerson);

            // Modify the cloned object
            clonedPerson.setName("Bob");
            clonedPerson.getAddress().setCity("Los Angeles");

            System.out.println("Original Person: " + originalPerson.getName() + ", " + originalPerson.getAddress().getCity());
            System.out.println("Cloned Person: " + clonedPerson.getName() + ", " + clonedPerson.getAddress().getCity());
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
class Address implements Serializable {
    private String city;

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

    public String getCity() {
        return city;
    }

    public void setCity(String city){
        this.city=city;
    }
}

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 void setName(String name){
        this.name=name;
    }

    public Address getAddress() {
        return address;
    }
}

在这里插入图片描述

3. 第三方工具

除此之外,还有一些第三方工具可以实现对象克隆,例如 Apache Commons BeanUtils 库的 BeanUtils.cloneBean() 方法和 Spring Framework 的 ObjectUtils.clone() 方法。

(1) Apache Commons BeanUtils 库

使用 BeanUtils.cloneBean() 方法可以对一个对象进行浅拷贝。

Person person1 = new Person("Alice", 20);
Person person2 = BeanUtils.cloneBean(person1);

(2) Apache Commons Lang 库

Apache Commons Lang 库提供了 SerializationUtils.clone() 方法,可以对对象进行深拷贝。

Person person1 = new Person("Alice", 20);
Person person2 = SerializationUtils.clone(person1);

(3) Spring Framework

使用 Spring Framework 的 ObjectUtils.clone() 方法可以对一个对象进行深拷贝。

Person person1 = new Person("Alice", 20);
Person person2 = (Person) ObjectUtils.clone(person1);

(4) Kryo 序列化库

Kryo 是一种快速、高效的 Java 序列化库,可以用于实现对象的深拷贝。使用 Kryo 序列化库实现对象的克隆需要先定义一个 Kryo 对象,然后对需要克隆的对象进行序列化和反序列化。例如:

Kryo kryo = new Kryo();
kryo.setRegistrationRequired(false);

Person person1 = new Person("Alice", 20);
Person person2 = kryo.copy(person1);

(5) FST 序列化库

FST 是一种基于字节码的 Java 序列化库,可以用于实现对象的深拷贝。使用 FST 序列化库实现对象的克隆需要先定义一个 FSTConfiguration 对象,然后对需要克隆的对象进行序列化和反序列化。

FSTConfiguration configuration = FSTConfiguration.createDefaultConfiguration();

Person person1 = new Person("Alice", 20);
Person person2 = (Person) configuration.asObject(configuration.asByteArray(person1));

需要注意的是,如果要克隆的对象中包含了集合、数组、Map 或其他引用类型的属性,需要保证这些属性的类型也是可克隆的或可序列化的,否则可能会导致克隆出来的对象不完整或者抛出异常。此外,在实现克隆时,还需要考虑线程安全等问题。使用第三方库实现对象克隆可能会带来一定的性能开销和额外的依赖,因此需要权衡利弊,选择适合自己的实现方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1206559.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

科研绘图与学术图表绘制:从入门到精通

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 一、入门篇 1.1 软件介…

云原生Kubernetes系列 | 通过容器互联搭建wordpress博客系统

云原生Kubernetes系列 | 通过容器互联搭建wordpress博客系统 通过容器互联搭建一个wordpress博客系统。wordpress系统是需要连接到数据库上的&#xff0c;所以wordpress和mysql的镜像都是需要的。wordpress在创建过程中需要指定一些参数。创建mysql容器时需要把mysql的数据保存…

(论文阅读31/100)Stacked hourglass networks for human pose estimation

31.文献阅读笔记 简介 题目 Stacked hourglass networks for human pose estimation 作者 Alejandro Newell, Kaiyu Yang, and Jia Deng, ECCV, 2016. 原文链接 https://arxiv.org/pdf/1603.06937.pdf 关键词 Human Pose Estimation 研究问题 CNN运用于Human Pose E…

YOLOv8-Seg改进:分割注意力系列篇 | 上下文增强和特征细化注意力ContextAggregation

🚀🚀🚀本文改进:多头上下文集成(Context Aggregation)的广义构建模块 ,引入YOLOv8二次创新; 🚀🚀🚀Context Aggregation小目标分割&复杂场景首选,实现涨点 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创…

⑥ 【MySQL函数】字符串函数、数值函数、日期函数、流程函数

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ MySQL函数 ⑥ 字符串函数、数值函数、日期函数…

【社会网络分析第5期】gephi使用指南

gephi数据可视化 gephi数据可视化1、软件安装2、数据处理与导入&#xff08;1&#xff09;导入节点&#xff08;2&#xff09;导入边&#xff08;3&#xff09;改变节点的颜色&#xff08;4&#xff09;根据pagerank调整节点的大小&#xff08;5&#xff09;根据pagerank调整边…

笔记本分屏怎么操作?3个方法提高工作效率!

“有朋友知道笔记本怎么才能实现分屏吗&#xff1f;我在工作时&#xff0c;经常需要来回切换屏幕&#xff0c;效率真的太低了&#xff0c;有什么方法可以实现两个屏幕同时使用吗&#xff1f;” 在现代生活中&#xff0c;多任务处理已成为常态&#xff0c;而笔记本分屏技术为用户…

放假通知!2024年全国中小学寒假时间发布!

进入冬季&#xff0c; 学生们都迫不及待地 期盼着寒假的到来。 近日&#xff0c;全国多地已经明确了 2024年中小学寒假的起止时间。 一起来看看你所在的城市寒假放几天 北京 据“首都教育”微信公众号消息&#xff0c; 普通中小学、中等职业学校 义务教育阶段2024年寒…

JTS: 21 MinimumBoundingCircle 最小包裹圆

文章目录 版本代码 版本 org.locationtech.jts:jts-core:1.19.0 链接: github 代码 package pers.stu.algorithm;import org.locationtech.jts.algorithm.MinimumBoundingCircle; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; …

ReportLab创建合同PDF

一、前言 有一个项目需要将电子签名后的报价合同和生成的发票发送给客户&#xff0c;这种发送给客户的文件一般都是使用PDF格式&#xff0c;主要是因为PDF特别适合阅读且不同平台打开文件格式不会变形&#xff0c;不过要在程序中生成PDF还是比较麻烦的&#xff0c;我们的发票是…

MySQL最新2023年面试题及答案,汇总版(7)【MySQL最新2023年面试题及答案,汇总版-第三十七刊】

文章目录 MySQL最新2023年面试题及答案&#xff0c;汇总版(7)01、NOW() 和 CURRENT_DATE() 有什么区别&#xff1f;02、CHAR和VARCHAR的区别&#xff1f;03、主键索引与唯一索引的区别&#xff1f;04、MySQL中有哪些不同的表格&#xff1f;05、SQL的生命周期&#xff1f;06、你…

nginx四层tcp负载均衡及主备、四层udp负载均衡及主备、7层http负载均衡及主备配置(wndows系统主备、负载均衡)

准备工作 服务器上安装、配置网络负载平衡管理器 windows服务器热备、负载均衡配置-CSDN博客 在windows服务器上安装vmware17 在windows上利用vmware17 搭建centos7 mini版本服务器 设置好静态ip地址&#xff08;因为windows 服务器上的网络负载平衡管理器不支持dhcp的服务器…

【git】解决git报错:ssh:connect to host github.com port 22: Connection timed out 亲测有效

如题&#xff0c;git使用中突然报错 ssh:connect to host github.com port 22: Connection timed out 通过查阅各种资料&#xff0c;得知原因可能是由于电脑的防火墙或者其他网络原因导致ssh连接方式 端口22被封锁。 解决方法 一&#xff1a;抛弃ssh连接方式&#xff0c;使…

YOLOv8-Seg改进:卷积变体系列篇 | PConv,减少冗余计算和内存访问可以更有效地提取空间特征 | CVPR2023 FasterNet

🚀🚀🚀本文改进:PConv,减少冗余计算和内存访问可以更有效地提取空间特征,引入到YOLOv8,与C2f结合实现二次创新; 🚀🚀🚀PConv 亲测在多个数据集能够实现涨点,同样适用于小目标分割 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习…

第2关:多表查询

任务描述 join操作符编程要求测试说明 任务描述 本关任务&#xff1a; 使用join操作符实现多表查询。 join操作符 1.笛卡尔积&#xff0c;RXS 可直接转换为SQL语句 2.等值连接&#xff0c;记作 可直接转换为SQL语句 3.自然连接&#xff0c;记作 可转换为SQL语句 4.左外连接…

对这套BI零售数据分析方案心动,是零售人天性

零售数据分析做了这么多年&#xff0c;难道真的没累积点经验&#xff0c;摸索出一条又快又能满足绝大多数需求的数据分析捷径&#xff1f;别人不知道&#xff0c;奥威BI还真就有这么一套标准化的BI零售数据分析方案&#xff0c;不管是服装零售、医药连锁、商超都能利用这套方案…

基于springboot实现小学家校一体“作业帮”系统项目【项目源码】

基于springboot实现小学家校一体“作业帮”系统演示 Java语言简介 Java是由SUN公司推出&#xff0c;该公司于2010年被oracle公司收购。Java本是印度尼西亚的一个叫做爪洼岛的英文名称&#xff0c;也因此得来java是一杯正冒着热气咖啡的标识。Java语言在移动互联网的大背景下具…

如何在 macOS 中删除 Time Machine 本地快照

看到这个可用82GB&#xff08;458.3MB可清除&#xff09; 顿时感觉清爽&#xff0c;之前的还是可用82GB&#xff08;65GB可清除&#xff09;&#xff0c;安装个xcode都安装不上&#xff0c;费解半天&#xff0c;怎么都解决不了这个问题&#xff0c;就是买磁盘情理软件也解决不了…

JavaScript中this关键字实践

● 在全局中&#xff0c; this关键字表示全局窗口 console.log(this);● 在严格模式下&#xff0c;this不指向函数本身&#xff0c;在非严格模式下&#xff0c;this指向全局窗口 console.log(this);const calcAge function (birthYear) {console.log(2037 - birthYear);cons…

Intellij IDEA 内存设置的问题 及解决

解决方案&#xff1a; 在IDEA上运行较大项目时&#xff0c;编译量很大&#xff0c;可能会报出 Error:java: java.lang.OutOfMemoryError: Java heap space 的错误&#xff0c;解决方法如下&#xff1a; java.lang.OutOfMemoryError是内存不足导致的&#xff0c;因此需要修改Id…