魔术方法 类 序列化_Java序列化魔术方法及其示例使用

魔术方法 类 序列化

在上一篇文章中, 您需要了解有关Java序列化的所有知识 ,我们讨论了如何通过实现Java序列化来启用类的可序列化性。
Serializable接口。 如果我们的类未实现Serializable接口,或者该类具有对非Serializable类的引用,则JVM将抛出NotSerializableException

可序列化类的所有子类型本身都是可序列化的,并且
Externalizable接口还扩展了可序列化。 所以即使我们
使用Externalizable自定义序列化过程,我们的类仍然是 Serializable

Serializable接口是一个标记接口,没有方法或字段,它的作用类似于JVM的标志。 ObjectInputStreamObjectOutputStream类提供的Java序列化过程完全由JVM控制。

但是,如果我们想添加一些其他逻辑来增强此正常过程,例如,我们可能希望在对敏感信息进行序列化/反序列化之前对其进行加密/解密。 Java为此提供了一些其他方法,我们将在此博客中讨论。

writeObject和readObject方法

希望自定义或添加一些其他逻辑以增强常规序列化/反序列化过程的可序列化类应提供
具有以下确切签名的writeObjectreadObject方法:

  • private void writeObject(java.io.ObjectOutputStream out) throws IOException
  • private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException

在您需要了解的有关Java序列化的所有知识下,已经对这些方法进行了详细讨论。

readObjectNoData方法

Serializable类的Java文档中所述,如果在序列化流未将给定类列出为要反序列化的对象的超类的情况下,如果我们想为其特定类初始化对象的状态,则应提供writeObject和具有以下确切签名的readObject方法:

  • private void readObjectNoData() throws ObjectStreamException

在接收方使用与发送方不同的反序列化实例类的版本,并且接收方的版本扩展了发送方版本未扩展的类的情况下,可能会发生这种情况。 如果序列化流已被篡改,也可能会发生这种情况。 因此,尽管源流“充满敌意”或不完整,但readObjectNoData对于正确初始化反序列化的对象很有用。

每个可序列化的类都可以定义自己的readObjectNoData方法。 如果可序列化的类未定义readObjectNoData方法,则在上述情况下,该类的字段将被初始化为其默认值。

writeReplace和readResolve方法

在将对象写入流时需要指定要使用的替代对象的可序列化类应为此特殊方法提供确切的签名:

  • ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException

当从流中读取实例时,需要指定替换的Serializable类应为此特殊方法提供确切的签名:

  • ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException

基本上, writeReplace方法允许开发人员提供将被序列化的替换对象,而不是原始对象。 在反序列化过程中使用了readResolve方法,用我们选择的另一个方法来替换反序列化的对象。

writeReplace和readResolve方法的主要用途之一是使用Serialized类实现单例设计模式。 我们知道, 反序列化过程每次都会创建一个新对象 ,它也可以用作深度克隆对象的方法,如果我们必须使类为单例,那么这样做就不好了。


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


readObject返回之后readResolve调用readResolve方法(相反,在writeObject之前(可能在另一个对象上)调用writeReplace )。 该对象在方法返回替换this返回到的用户对象ObjectInputStream.readObject并流中的对象中的任何进一步的反向引用。 我们可以使用writeReplace方法将序列化对象替换为null,以便不进行序列化,然后使用readResolve方法将反序列化的对象替换为单例实例。

validateObject方法

如果我们要在某些字段上执行某些验证,则可以通过实现ObjectInputValidation接口并重写
来自它的validateObject方法。

当我们通过从readObject方法调用ObjectInputStream.registerValidation(this, 0)注册此验证时,将自动调用validateObject方法。 在将流返回给您的应用程序之前,验证流是否未被篡改或数据有意义是非常有用的。

下面的示例涵盖了上述所有方法的代码

 public class SerializationMethodsExample { public static void main(String[] args) throws IOException, ClassNotFoundException { Employee emp = new Employee( "Naresh Joshi" , 25 ); System.out.println( "Object before serialization: " + emp.toString()); // Serialization serialize(emp); // Deserialization Employee deserialisedEmp = deserialize(); System.out.println( "Object after deserialization: " + deserialisedEmp.toString()); System.out.println(); // This will print false because both object are separate System.out.println(emp == deserialisedEmp); System.out.println(); // This will print false because both `deserialisedEmp` and `emp` are pointing to same object, // Because we replaced de-serializing object in readResolve method by current instance System.out.println(Objects.equals(emp, deserialisedEmp)); } // Serialization code static void serialize(Employee empObj) throws IOException { try (FileOutputStream fos = new FileOutputStream( "data.obj" ); ObjectOutputStream oos = new ObjectOutputStream(fos)) { oos.writeObject(empObj); } } // Deserialization code static Employee deserialize() throws IOException, ClassNotFoundException { try (FileInputStream fis = new FileInputStream( "data.obj" ); ObjectInputStream ois = new ObjectInputStream(fis)) { return (Employee) ois.readObject(); } }  }  Employee class implements Serializable, ObjectInputValidation { private static final long serialVersionUID = 2L; private String name; private int age; public Employee(String name, int age) { this .name = name; this .age = age; } // With ObjectInputValidation interface we get a validateObject method where we can do our validations. @Override public void validateObject() { System.out.println( "Validating age." ); if (age < 18 || age > 70 ) { throw new IllegalArgumentException( "Not a valid age to create an employee" ); } } // Custom serialization logic, // This will allow us to have additional serialization logic on top of the default one eg encrypting object before serialization. private void writeObject(ObjectOutputStream oos) throws IOException { System.out.println( "Custom serialization logic invoked." ); oos.defaultWriteObject(); // Calling the default serialization logic } // Replacing de-serializing object with this, private Object writeReplace() throws ObjectStreamException { System.out.println( "Replacing serialising object by this." ); return this ; } // Custom deserialization logic // This will allow us to have additional deserialization logic on top of the default one eg performing validations, decrypting object after deserialization. private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { System.out.println( "Custom deserialization logic invoked." ); ois.registerValidation( this , 0 ); // Registering validations, So our validateObject method can be called. ois.defaultReadObject(); // Calling the default deserialization logic. } // Replacing de-serializing object with this, // It will will not give us a full proof singleton but it will stop new object creation by deserialization. private Object readResolve() throws ObjectStreamException { System.out.println( "Replacing de-serializing object by this." ); return this ; } @Override public String toString() { return String.format( "Employee {name='%s', age='%s'}" , name, age); }  } 

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

翻译自: https://www.javacodegeeks.com/2019/09/java-serialization-magic-methods-and-their-uses-with-example.html

魔术方法 类 序列化

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

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

相关文章

算法证明_CFR+算法证明过程

在介绍CFR算法之前&#xff0c;我们首先介绍一下基础概念。在CFR算法中&#xff0c;counterfactual utility被定义为以下形式&#xff1a;然后在regret的基础上&#xff0c;CFR算法定义了一个regretlike value&#xff0c;注意在这里CFR算法的regret为一个累加值&#xff0c;而…

java继承中的 equals + hashCode+toString

【0】README 0.1&#xff09;本文转自 core java volume 1&#xff0c; 旨在理清 equals hashCode方法&#xff1b; 0.2&#xff09; 特别说明&#xff1a; 在java中&#xff0c; 只有基本类型不是对象&#xff0c; 例如&#xff0c;数值&#xff0c; 字符和布尔类型的值都不…

纹理和基元_自定义基元和DTO的(反)序列化和验证

纹理和基元最近&#xff0c;我们为您提供了新的HTTP框架HttpMate。 在介绍性文章中 &#xff0c;我们将请求和响应映射到域对象称为“最复杂的技术细节”&#xff0c;以及如何通过另一个伴侣MapMate帮助我们。 实际上&#xff0c;当将请求属性映射到您的域对象时&#xff0c;M…

vim 常用命令

文章目录普通命令模式下技巧汇总切换到插入模式切换到可视模式切换至底行命令模式复制内容复制命令的记忆技巧粘贴/恢复修改/改写删除/剪切字符大小写切换选择文本游标移动剪切文本/移动文本滚屏/翻页撤回查看文档状态查找/搜索字符串查看历史命令查看历史搜索记录多窗口操作保…

常见花材的固定的方法有哪些_旋流器常见的故障及处理方法有哪些?

旋流器除了用在磨矿循环中的分级作业外&#xff0c;还可以用于脱泥、脱水以及脱除浮选药剂等。此外&#xff0c;还可以用做重悬浮液选矿&#xff0c;其分选粒度可达0.1毫米左右。旋流器有许多优点&#xff0c;构造简单&#xff0c;没有运动部件&#xff0c;单位容积的处理能力大…

二叉堆(优先队列)

【0】README 0.1&#xff09; 本文总结于 数据结构与算法分析&#xff0c;但源代码均为原创&#xff1b;旨在理清二叉堆&#xff08;优先队列&#xff09; 堆的其他操作及其应用&#xff0c; 以便让朋友些知道为什么要学习优先队列&#xff1b; 【1】二叉堆 1.0&#xff09;…

java自定义外部接口_如何使用可外部化的接口在Java中自定义序列化

java自定义外部接口在上一篇文章“用示例介绍的有关Java序列化的一切”中 &#xff0c;我解释了如何使用以下方法序列化/反序列化一个对象 Serializable接口&#xff0c;还说明了如何使用writeObject和readObject方法自定义序列化过程。 Java序列化过程的缺点 但是这些自定义…

python训练营朋友圈留言_用Python发一个高逼格的朋友圈【附代码】

今天二胖要给大家介绍一个Python库&#xff1a;PIL(Python Image Library)下面我们用一个实际的例子看看50行python代码可以做什么神奇的事情这是二胖发的一个朋友圈切图前是一张图切图后就是九张图啦成功霸屏除了可以处理规整的正方形图片还可以处理非规则的图片比如下面这张宽…

vim 编辑器的快捷键

文章目录命令终端界面滚屏命令终端页签切换缓存区切换/文件切换分割窗口/打开新窗口切换窗口移动/旋转/移出窗口关闭窗口调整窗口大小底行命令模式下的编辑快捷键vim 很多指令或者快捷键是大小写敏感。命令终端界面滚屏 快捷键说明Fn ←向上滚屏到开始处Fn →向下滚屏到末尾…

关于二叉堆(优先队列)的其他操作及其应用

【0】README 0.1&#xff09;本文总结于 数据结构与算法分析&#xff1b;源代码均为原创&#xff0c; 旨在了解到我们学习了优先队列后&#xff0c;还能干些什么东西出来&#xff0c; 增加学习的interest&#xff1b; 0.2&#xff09;以下列出了 关于二叉堆&#xff08;优先队…

gradle junit5_JUnit 5和Selenium –使用Gradle,JUnit 5和Jupiter Selenium设置项目

gradle junit5Selenium是一组支持浏览器自动化的工具和库&#xff0c;主要用于Web应用程序测试。 Selenium的组件之一是Selenium WebDriver&#xff0c;它提供客户端库&#xff0c;JSON有线协议&#xff08;与浏览器驱动程序进行通信的协议&#xff09;和浏览器驱动程序。 Sele…

ubuntu 两块硬盘挂载不上_win10 轉 Ubuntu

目前用了win10兩三年。發現越來越慢&#xff0c;況且已習慣mac OS&#xff0c;所以想用自己的機子來裝個雙系統Linux&#xff0c;慢慢的將win的東西都轉到Ubuntu上。已清空一個磁盤300G,打算就是在這300G裡裝一個Ubuntu&#xff0c;不知道是否夠用&#xff08;雖然很想裝在三星…

包+类导入+静态导入+类放入包中+包作用域

【0】README 0.1&#xff09;本文转自 core java volume 1&#xff0c; 旨在理清 包和类导入的相关知识&#xff1b; 【1】 包 1.1&#xff09; java 允许使用包将类组织起来&#xff0c;包可以方便组织代码&#xff0c;并将自己的代码与别人提供的代码库分开管理&#xff1b…

selenium自动化测试_使用Selenium自动化测试处理多个浏览器选项卡

selenium自动化测试使用Selenium进行自动化测试一直是将萌芽的自动化测试人员培养为专业人员的生命线。 Selenium是开源的&#xff0c;在全球范围内被广泛采用。 结果&#xff0c;您会得到社区的大力支持。 提供了与Selenium绑定的不同语言的多种框架。 因此&#xff0c;您已经…

qt和c#怎么选_请问目前做windows桌面应用程序,MFC、QT、C#哪个更好?

回答问题之前&#xff0c;先装个逼——没有主导过生命周期三年以上的桌面软件项目的&#xff0c;闭嘴。你连一个桌面软件项目的生命周期都没经历过&#xff0c;你凭什么做技术选型&#xff1f;凭信仰吗&#xff1f;装逼结束&#xff0c;正文开始。首先&#xff0c;非主流技术和…

java 白皮书的关键术语

【0】README 0.1&#xff09; 本文转自 core java volume 1&#xff0c;仅供了解&#xff0c;所谓爱屋及乌嘛&#xff1b; 0.2&#xff09; java的设计者编写了颇有影响力的白皮书&#xff0c;用来解释设计的初衷以及完成的情况&#xff0c;并发布了一个摘要&#xff1b;【1】…

当集合a为空集时a的取值范围_高中数学必修一第一章集合分节练习和章末测试题含答案[1] 2...

高中数学必修1 第一章 集合 分节练习和章末综合测试题含答案1 集合的含义与表示1、下列各组对象能否组成一个集合&#xff1f;(1)接近于0的数的全体&#xff1b; (2)2的近似值的全体&#xff1b; (3)平面上到点O 的距离等于1的点的全体&#xff1b; (4)正三角形的全体&#xff…

spring jpa 流式_从响应式Spring Data存储库流式传输实时更新

spring jpa 流式这篇文章详细介绍了从数据库到对该数据感兴趣的任何其他组件进行流更新的幼稚实现。 更准确地说&#xff0c;如何更改Spring Data R2DBC存储库以向相关订阅者发出事件。 对R2DBC和Spring的一点背景知识将对这篇文章有所帮助。 我以前的著作《 使用 Microsoft S…

弹窗页面交互_UI进阶知识-信息提交类弹窗该如何设计?

原文作者&#xff1a;风筝KK 信息提交类弹窗大家应该都比较熟悉&#xff0c;和其他弹窗的区别在于他有输入、选择等操作&#xff0c;比如我们常见的输入验证码、留言回复、充值转账、任务设置等。看上去设计都比较简单&#xff0c;但是当你验收时就会发现问题&#xff0c;为什么…