java序列化深克隆_如何在内存序列化中使用Java深克隆对象

java序列化深克隆

在我以前的文章中,我解释了深度克隆和浅层克隆之间的区别 , 以及复制构造函数和防御性复制方法比默认的Java克隆如何更好。

使用复制构造函数和防御性复制方法进行的Java对象克隆当然具有某些优势,但是我们必须显式编写一些代码才能在所有这些方法中实现深度克隆。 而且,仍然有可能我们会错过某些东西并且不会得到深克隆的对象。

正如在Java中创建对象的5种不同方式中所讨论的那样,反序列化序列化对象会创建一个状态与序列化对象相同的新对象。 因此,与上述克隆方法类似,我们也可以使用对象序列化和反序列化来实现深度克隆功能,并且通过这种方法,我们不必担心或编写用于深度克隆的代码,默认情况下会得到它。

但是,使用序列化克隆对象会带来一些性能开销,如果我们只需要克隆对象并且不需要将其持久保存在文件中以备将来使用,则可以通过使用内存中序列化来改进它。

我们将使用以下Employee类作为示例,其name
作为状态的dojskills ,对于深度克隆,我们无需担心code> name字段,因为它是一个String对象,默认情况下所有
弦在本质上是不变的 。

您可以在《 如何在Java中创建不可变的类》以及《 为什么String是不可变的和Final》上阅读有关不可变性的更多信息。

 Employee class implements Serializable { private static final long serialVersionUID = 2L; private String name; private LocalDate doj; private List<String> skills; public Employee(String name, LocalDate doj, List<String> skills) { this .name = name; this .doj = doj; this .skills = skills; } public String getName() { return name; } name; } public LocalDate getDoj() { return doj; } doj; } public List<String> getSkills() { return skills; } skills; } // Method to deep clone a object using in memory serialization public Employee deepClone() throws IOException, ClassNotFoundException { // First serializing the object and its state to memory using ByteArrayOutputStream instead of FileOutputStream. ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bos); out.writeObject( this ); // And then deserializing it from memory using ByteArrayOutputStream instead of FileInputStream. // Deserialization process will create a new object with the same state as in the serialized object, ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream in = new ObjectInputStream(bis); return (Employee) in.readObject(); } @Override public String toString() { return String.format( "Employee{name='%s', doj=%s, skills=%s}" , name, doj, skills); } @Override public boolean equals(Object o) { if ( this == o) return true ; if (o == null || getClass() != o.getClass()) return false ; Employee employee = (Employee) o; return Objects.equals(name, employee.name) && Objects.equals(doj, employee.doj) && Objects.equals(skills, employee.skills); } @Override public int hashCode() { return Objects.hash(name, doj, skills); }  } 

为了深度克隆Employee类的对象,我提供了一个
deepClone()方法,通过使用将对象序列化到内存
ByteArrayOutputStream而不是FileOutputStream并使用ByteArrayInputStream而不是FileInputStream将其反序列化。 在这里,我们将对象序列化为字节,然后再次将其从字节反序列化为对象。

Employee类实现Serializable接口来实现序列化,这有其自身的劣势,我们可以通过使用Externalizable接口来自定义序列化过程来克服其中的某些劣势。

我们可以在下面的测试中运行,以了解我们的克隆方法是深层克隆还是浅层克隆,此处所有==操作将返回false(因为两个对象是分开的),而所有equals将返回true(因为两者具有相同的内容)。

 public static void main(String[] args) throws IOException, ClassNotFoundException { Employee emp = new Employee( "Naresh Joshi" , LocalDate.now(), Arrays.asList( "Java" , "Scala" , "Spring" )); System.out.println( "Employee object: " + emp); // Deep cloning `emp` object by using our `deepClone` method. Employee clonedEmp = emp.deepClone(); System.out.println( "Cloned employee object: " + clonedEmp); System.out.println(); // All of this will print false because both objects are separate. System.out.println(emp == clonedEmp); System.out.println(emp.getDoj() == clonedEmp.getDoj()); System.out.println(emp.getSkills() == clonedEmp.getSkills()); System.out.println(); // All of this will print true because `clonedEmp` is a deep clone of `emp` and both have the same content. System.out.println(Objects.equals(emp, clonedEmp)); System.out.println(Objects.equals(emp.getDoj(), clonedEmp.getDoj())); System.out.println(Objects.equals(emp.getSkills(), clonedEmp.getSkills()));  } 

我们知道反序列化过程每次都会创建一个新对象,如果我们必须使我们的类单身,那将是不好的。 这就是为什么我们需要覆盖和禁用单例类的序列化,这可以通过提供writeReplace和readResolve方法来实现。

与序列化类似,Java克隆也不能与单例模式一起使用,这就是为什么我们也需要覆盖和禁用它。 我们可以通过实现克隆的方式来做到这一点,以便它要么抛出
CloneNotSupportedException或每次都返回相同的实例。

您可以在Java Cloning和Java上阅读有关Java克隆和序列化的更多信息。
Java序列化主题。

您可以在此找到本文的完整源代码。
Github存储库 ,请随时提供宝贵的反馈。

翻译自: https://www.javacodegeeks.com/2019/08/deep-clone-using-java-memory-serialization.html

java序列化深克隆

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

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

相关文章

java反射机制+继承设计技巧

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 java反射机制 &#xff1b;最后还顺带提出了 继承设计的技巧&#xff1b; 【1】反射相关 1&#xff09;反射定义&#xff1a;能够分析类能力的程序称为反射&#xff1b; 2&…

60秒计时器的仿真电路_基于伏秒平衡的同步整流方案探讨

为了提高电源的效率和功率密度&#xff0c;尤其是低输出电压的应用场合&#xff0c;同步整流是不可或缺的。图1-1 反激输出二极管损耗比如上图的反激电源如果输出二极管 Vf0.7V&#xff0c;输出电压 Vout3V 则效率不会高于3/(30.7)81%。为了提升效率一般会选用低导通压降的肖特…

利用反射机制创建新类的两种方式及比较

【0】README 0.1&#xff09; 本文描述源代码均 转自 http://blog.csdn.net/fenglibing/article/details/4531033 &#xff0c; 旨在深入理解 如何利用反射机制创建类实例&#xff1b; 0.2&#xff09; 转载的源代码&#xff0c;参见 https://github.com/pacosonTang/core-ja…

如何设计高效测试用例_高效的企业测试-单元和用例测试(2/6)

如何设计高效测试用例在本系列的第一部分中&#xff0c;我们看到了有效测试应满足的一些普遍适用的原则和约束。 在这一部分中&#xff0c;我们将仔细研究代码级单元测试和组件或用例测试。 单元测试 单元测试验证单个单元&#xff08;通常是类&#xff09;的行为&#xff0c…

php mysql study_PHPstudy升级mysql数据库

首先查看phpstudy的mysql版本&#xff1a;方法一 使用mysql的version函数&#xff1a;mysql> selectversion();方法二 status命令mysql> status&#xff1b;方法三 直接在cmd下输入命令查看mysql -vmysql --help下面开始升级数据库1、备份好自己的数据库2、清空phpstudy…

selenium 等待_Selenium等待:内隐,外显,流利和睡眠

selenium 等待Selenium等待页面加载在Selenium脚本中起着重要的作用。 它们有助于使它们不易剥落&#xff0c;更可靠。 Selenium提供多次等待&#xff0c;以根据某些条件在脚本执行中提供足够的等待或暂停。 从而确保您在使用Selenium执行自动化测试时不会导致脚本失败。 在本教…

java接口概述

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 java 接口概念 &#xff1b; 0.2&#xff09;接口技术&#xff1a; 这种技术主要用来描述类具有什么功能&#xff0c; 并不给出每个功能的具体实现&#xff1b; 一个类可以实现多…

通过aws部署推荐系统_通过AWS Elastic Beanstalk轻松进行Spring Boot部署

通过aws部署推荐系统朋友不允许朋友写用户身份验证。 厌倦了管理自己的用户&#xff1f; 立即尝试Okta的API和Java SDK。 数分钟之内即可在任何应用程序中对用户进行身份验证&#xff0c;管理和保护。 几乎所有应用程序都依赖于身份验证。 开发人员以及雇用他们的公司都想确认…

图论算法基础

【0】README 0.1&#xff09;本文总结于 数据结构与算法分析&#xff0c; 旨在复习数据结构中图论算法的基础知识&#xff1b; 【1】图论若干相关定义 1.1&#xff09;图G定义&#xff1a;一个图G&#xff08;V&#xff0c;E&#xff09;由顶点及集V 和 边集E组成&#xff0c…

mysql 表丢失_Mysql数据库备份 部分数据表丢失 Mysql table doesn't exist 解决

问题&#xff1a;直接拷贝data下的数据库数据进行备份&#xff0c;重装升级了数据库&#xff0c;直接复制备份数据到新的数据库data目录下&#xff0c;发现部分数据表不见了。原因分析&#xff1a;以表“Table”为例:如类型是MyISAM, 数据文件则以”Table.frm”&#xff0c;”T…

aws 删除ec2实例_如何在AWS EC2实例上部署Spring Boot应用程序

aws 删除ec2实例你好朋友&#xff0c; 在本教程中&#xff0c;我们将看到如何在AWS EC2实例上部署Spring Boot应用程序。 这是我们将要执行的步骤。 1.使用Spring Boot Initialiser创建一个Spring Boot项目。 2.创建一个休息端点&#xff0c;部署后我们可以访问 3.启动EC2…

jdbc操作mysql数据库_JDBC操作MySQL数据库(一)

连接MySQL数据库连接数据源有两种方式&#xff1a;1)通过DriverManager类2)通过DataSource接口及JNDI资源获得连接DriverManager类的路径为java.sql.DriverManager&#xff0c;它主要完成驱动程序的装载和建立新的数据库连接。其常用方法如下&#xff1a;* getConnection (Stri…

只读事务上下文_我可以/应该在事务上下文中使用并行流吗?

只读事务上下文介绍 长话短说&#xff0c;您不应在并行流中使用事务。 这是因为并行流中的每个线程都有其自己的名称&#xff0c;因此它确实参与了事务。 Streams API旨在在某些准则下正常工作。 实际上&#xff0c;为了受益于并行性&#xff0c;不允许每个操作更改共享对象的…

mysql多表查询详解_MySQL多表查询详解上

时光在不经意间&#xff0c;总是过得出奇的快。小暑已过&#xff0c;进入中暑&#xff0c;太阳更加热烈的绽放着ta的光芒&#xff0c;...在外面被太阳照顾的人们啊&#xff0c;你们都是勤劳与可爱的人啊。在房子里已各种姿势看我这篇这章的你&#xff0c;既然点了进来&#xff…

无权最短路径

【0】README 0.1&#xff09; 本文总结于 数据结构与算法分析&#xff0c; 源代码均为原创&#xff0c; 旨在理解 无权最短路径 的思想并用源代码加以实现&#xff1b; 【1】无权最短路径相关概念&#xff08;边的权值赋值为1&#xff09; 1.1&#xff09;概述&#xff1a;下…

java 键入_在Java中键入Safe SQL

java 键入字符串&#xff0c;字符串&#xff0c;字符串 无论您使用的是JPA &#xff0c; MyBatis还是Spring Data JDBC之类的框架&#xff0c;总会最终将SQL语句声明为Java String。 这种方法的问题在于&#xff0c;您必须为每个语句编写测试&#xff0c;以确保它甚至是有效SQ…

filter过滤后重新添加_Spring Boot 2.X(十):自定义注册 Servlet、Filter、Listener

前言在 Spring Boot 中已经移除了 web.xml 文件&#xff0c;如果需要注册添加 Servlet、Filter、Listener 为 Spring Bean&#xff0c;在 Spring Boot 中有两种方式&#xff1a;使用 Servlet 3.0 API 的注解 WebServlet、WebFilter、Listener 用来配置。Spring Boot JavaConfig…

对象克隆+深浅拷贝

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 对象拷贝 的概念 &#xff0c; 特别是对 深拷贝和浅拷贝 的理解&#xff1b; 0.2&#xff09; 最后&#xff0c;我们还要看一个 clone 的荔枝&#xff1b; 【1】对象克隆相关 1…

read cache_通过READ-BEHIND CACHE控制您的慢速生产者

read cache在我们的互联世界中&#xff0c;我们经常使用我们不拥有或无权改善的API中的数据。 如果一切顺利&#xff0c;他们的表现就会很好&#xff0c;每个人都会高兴。 但是太多次&#xff0c;我们不得不使用延迟小于最佳延迟的 API。 当然&#xff0c;答案是缓存该数据 。…

azkaban mysql参数_azkaban参数详解

参数传递是调度字体工作流运行时非常重要的一部分&#xff0c;工作流的执行&#xff0c;单个作业的执行&#xff0c;多个工作流之间的依赖执行&#xff0c;历史任务重算&#xff0c;都涉及到参数传递和同步。1 参数类型综述azkaban的工作流中的参数可以分为如下几个类型&#x…