java中可定制的序列化过程 writeObject与readObject

为什么 ArrayList 底层数组要使用 `transient` 关键字? ArrayList通过自定义的和readObject方法来实现序列化和反序列化。这些方法位于ArrayList的内部,用于处理内部数组的序列化。在 Java 编程中,ArrayList的底层数组使用transient关键字标记,以避免序列化未使用的空间,节省空间并提高性能。通过自定义的和readObject方法,ArrayList可以更灵活地控制序列化过程,只序列化实际存储的元素。理解transient关键字的作用和ArrayList的自定义序列化方法,有助于编写更高效、更易于维护的代码。 阅读详情

来源于:【http://bluepopopo.iteye.com/blog/486548】

在Java中使用Serialization相当简单。如果你有一些对象想要进行序列化,你只需实现Serializable接口。然后,你可以使用ObjectOutputStream将该对象保存至文件或发送到其他主机。所有的non-transient和non-static字段都将被序列化,并且由反序列化重构造出一模一样的对象联系图(譬如许多引用都指向该对象)。但有时你可能想实现你自己的对象序列化和反序列化。那么你可以在某些特定情形下得到更多的控制。来看下面的简单例子。 
Java代码   收藏代码
  1. class SessionDTO implements Serializable {  
  2.     private static final long serialVersionUID = 1L;  
  3.     private int data; // Stores session data  
  4.   
  5.     // Session activation time (creation, deserialization)  
  6.     private long activationTime;   
  7.   
  8.     public SessionDTO(int data) {  
  9.         this.data = data;  
  10.         this.activationTime = System.currentTimeMillis();  
  11.     }  
  12.   
  13.     public int getData() {  
  14.         return data;  
  15.     }  
  16.   
  17.     public long getActivationTime() {  
  18.         return activationTime;  
  19.     }  
  20. }  

以下是序列化上述class到文件和其反序列化的主函数。 
Java代码   收藏代码
  1. public class SerializeTester implements Serializable {  
  2.     public static void main(String... strings) throws Exception {  
  3.         File file = new File("out.ser");  
  4.   
  5.         ObjectOutputStream oos = new ObjectOutputStream(  
  6.             new FileOutputStream(file));  
  7.         SessionDTO dto = new SessionDTO(1);  
  8.         oos.writeObject(dto);  
  9.         oos.close();  
  10.   
  11.         ObjectInputStream ois = new ObjectInputStream(  
  12.             new FileInputStream(file));  
  13.         SessionDTO dto = (SessionDTO) ois.readObject();  
  14.   
  15.         System.out.println("data : " + dto.getData()  
  16.             + " activation time : " + dto.getActivationTime());  
  17.         ois.close();  
  18.     }  
  19. }  

类SessionDTO展现的是要在两个服务器之间传输的session。它包含了一些信息在字段data上,该字段需要被序列化。但是它还有另外一个字段activationTime,该字段应该是session对象第一次出现在任意服务器上的时间。它不在我们想要传输的信息之列。这个字段应该在反序列化之后在赋值。进一步来说,没必要把它放在stream中在服务器中传递,因为它占据了不必要的空间。 

解决这种情况可以使用writeObject和readObject。有可能你们有一些人没有听说过它们,那是因为它们在许多Java书籍中给忽略了,而且它们们也不是众多流行Java考试的一部分。让我们用这些方法来重写SessionDTO: 
Java代码   收藏代码
  1. class SessionDTO implements Serializable {  
  2.     private static final long serialVersionUID = 1L;  
  3.     private transient int data; // Stores session data  
  4.   
  5.     //Session activation time (creation, deserialization)  
  6.     private transient long activationTime;   
  7.   
  8.     public SessionDTO(int data) {  
  9.         this.data = data;  
  10.         this.activationTime = System.currentTimeMillis();  
  11.     }  
  12.   
  13.     private void writeObject(ObjectOutputStream oos) throws IOException {  
  14.         oos.defaultWriteObject();  
  15.         oos.writeInt(data);  
  16.         System.out.println("session serialized");  
  17.     }  
  18.   
  19.     private void readObject(ObjectInputStream ois) throws IOException,  
  20.             ClassNotFoundException {  
  21.         ois.defaultReadObject();  
  22.         data = ois.readInt();  
  23.         activationTime = System.currentTimeMillis();  
  24.         System.out.println("session deserialized");  
  25.     }  
  26.   
  27.     public int getData() {  
  28.         return data;  
  29.     }  
  30.   
  31.     public long getActivationTime() {  
  32.         return activationTime;  
  33.     }  
  34. }  

方法writeObject处理对象的序列化。如果声明该方法,它将会被ObjectOutputStream调用而不是默认的序列化进程。如果你是第一次看见它,你会很惊奇尽管它们被外部类调用但事实上这是两个private的方法。并且它们既不存在于java.lang.Object,也没有在Serializable中声明。那么ObjectOutputStream如何使用它们的呢?这个吗,ObjectOutputStream使用了反射来寻找是否声明了这两个方法。因为ObjectOutputStream使用getPrivateMethod,所以这些方法不得不被声明为priate以至于供ObjectOutputStream来使用。 

在两个方法的开始处,你会发现调用了defaultWriteObject()和defaultReadObject()。它们做的是默认的序列化进程,就像写/读所有的non-transient和 non-static字段(但他们不会去做serialVersionUID的检查).通常说来,所有我们想要自己处理的字段都应该声明为transient。这样的话,defaultWriteObject/defaultReadObject便可以专注于其余字段,而我们则可为这些特定的字段(译者:指transient)定制序列化。使用那两个默认的方法并不是强制的,而是给予了处理复杂应用时更多的灵活性。 

你可以从 这里或 这里读到更多有关于序列化的知识。 

自己再补充一些: 

1.Write的顺序和read的顺序需要对应,譬如有多个字段都用wirteInt一一写入流中,那么readInt需要按照顺序将其赋值; 

2.Externalizable,该接口是继承于Serializable ,所以实现序列化有两种方式。区别在于Externalizable多声明了两个方法readExternal和writeExternal,子类必须实现二者。Serializable是内建支持的也就是直接implement即可,但Externalizable的实现类必须提供readExternal和writeExternal实现。对于Serializable来说,Java自己建立对象图和字段进行对象序列化,可能会占用更多空间。而Externalizable则完全需要程序员自己控制如何写/读,麻烦但可以有效控制序列化的存储的内容。 

3.正如Effectvie Java中提到的,序列化就如同另外一个构造函数,只不过是有由stream进行创建的。如果字段有一些条件限制的,特别是非可变的类定义了可变的字段会反序列化可能会有问题。可以在readObject方法中添加条件限制,也可以在readResolve中做。参考56条“保护性的编写readObject”和“提供一个readResolve方法”。 

4.当有非常复杂的对象需要提供deep clone时,可以考虑将其声明为可序列化,不过缺点也显而易见,性能开销。

IEEE论文接收后,收到Proof邮件别慌!手把手教你48小时内搞定校样(附详细截图) 本文详细解析了IEEE论文接收后Proof校样的全流程,从邮件关键信息解码到精准修改标注,提供48小时内高效完成校样的实战指南。涵盖登录技巧、文件验证、修改标注黄金法则及九宫格检查清单,帮助作者避免常见错误,确保论文顺利发表。 阅读详情

相关推荐

adas硬件_ADAS智能辅助驾驶系统硬件在环(HIL)测试之硬件介绍

这篇主要分享的是ADAS融合系统的HIL测试系统的硬件结构及其作用,其主要包括上位机、机柜、雷达模拟器系统、雷达暗箱系统以及视频暗箱。 上位机 上位机主要运行HIL测试系统的相关软件,测试人员所有的前期准备工作与测试操作均在上面进行,并监控测试结果,其通过网口实现与NI实时机的通信,上位机将VeriStand项目工程下载至NI实时机运行。机柜 机柜主要由可编程电源...

weixin_39580748的博客 2243

ArrayList的transient探究

transient修饰符的作用

Revolver_的博客 772

comsol 多物理场仿真流程-以开关柜为例

1、主要方法 在SolidWorks中对于开关柜的内部与外部结构进行建模,生成能够导入软件计算的3D模型。将SolidWorks中的模型导入comsol软件中,设置参数进行多物理场耦合仿真。 1、具体步骤 删除高压开关柜中对其内部电磁环境无较大影响的结构,如低压测量柜、断路器内部结构等。 导入模型:将厂家提供的3D模型转化为solidworks结构模型。 修复模型:修复已转化模型中转化错误的部分、修复已转化模型中非实体部分、修复已转化模型中重叠实体部分 化简模型:去除过于...

健忘16的博客 7020

什么是writeObject 和readObject?可定制的序列化过程

这篇文章很直接,简单易懂。尝试着翻译一下 :wink: ,原文是[b][url=http://www.javablogging.com/what-are-writeobject-and-readobject-customizing-the-serialization-process/]What are writeObject and readObject? Customizing the seri...

半支香烟 1185

现代密码学5.3--Hash and MAC

现代密码学5.3--Hash and MAC 博主正在学习INTRODUCTION TO MODERN CRYPTOGRAPHY (Second Edition) --Jonathan Katz, Yehuda Lindell,做一些笔记供自己回忆,如有错误请指正。整理成一个系列现代密码学,方便检索。 第二章定义了完美安全及其对应的密码方案“一次一密”, 第三章介绍了多种安全定义 3.1-3.3 计算安全,PRG和基于PRG构造的满足计算安全的密码方案; 3.4-3.5 CPA安全,PRF和基于PRF构

qq_41545715的博客 686

四旋翼无人机Matlab建模

本文主要分享一下四旋翼无人机的建模过程,然后在Matlab的simulink模块搭建起四旋翼无人机的模型,下一章将结合这个模型设计双环PID控制器并调节参数。 一、无人机建模过程

qq_36903625的博客 3万+

ArrayList 的数组为什么修饰成tansient

ArrayList 的数组为什么修饰成tansient ArrayList底层是基于动态数组实现的,数组的长度是动态变化的,初始化长度为0,当添加一个元素的时候,数组的长度就会发生变化(不得不说,开发人员对内存优化的很到位)。可以看到elementData数组是transient修饰的,而被transient` 修饰的变量不会被序列化。 而对象的序列化和反序列化是通过调用方法 writeObject() 和 readObject() 完成,我们发现,ArrayList 自己实现这两个方法 假如element

qq_35274666的博客 633

别再手动算重量了!用C++给UG/NX写个自动计算零件质量与质心的插件(附完整源码)

本文详细介绍了如何使用C++为UG/NX开发智能质量分析插件,实现零件质量与质心的自动计算。通过结合NXOpen和UF_MODL API,设计高效的数据结构和批量处理机制,大幅提升机械设计效率。文章包含完整源码和实用技巧,帮助工程师告别手动计算,适用于复杂装配体的自动化工程计算。

weixin_30247307的博客 133

ArrayList数组为什么要用transient修饰?

ArrayList数组为什么要用transient修饰? 序列化 我们知道对象是不能直接进行网络传输的,必须要转化为二进制字节流进行传输。序列化就是将对象转化为字节流的过程。同理,反序列化就是从字节流构建对象的过程。 对于 Java 对象来说,如果使用 JDK 的序列化实现。对象只需要实现 java.io.Serializable 接口。 可以使用 ObjectOutputStream() 和 ...

chengbinbbs的专栏 2996

PyTorch生成式人工智能(25)——基于Transformer实现机器翻译

不同于循环神经网络 (RNN) 按顺序处理数据,Transformer 以并行的方式处理输入数据(例如句子)。这种并行处理提高了效率,但并未使其能够识别输入的顺序。为了解决这个问题,Transformer 向输入的词嵌入中添加了位置编码。这些位置编码是分配给输入序列中每个位置的独特向量,其维度与输入词嵌入对齐。本节将以英语到法语的翻译为例,通过介绍如何训练 Transformer 模型将英语句子转换为法语,深入理解 Transformer 的架构及自注意力机制的运作方式。

盼小辉丶的博客 2768

YOLOv12改进策略【模型轻量化】| 替换骨干网络为EfficientNet v1 高效的移动倒置瓶颈结构

本文记录的是基于。采用了创新性的方法,通过精心平衡网络和来提升性能。本文将的设计优势融入YOLOv12中,提升YOLOv12的性能与效率,使其在目标检测任务中表现更为出色。本文配置了原模型中的共种不同大小的模型结构,以满足不同的需求。

Limiiiing的博客 964

JAVA对象流序列化时的readObject,writeObject,readResolve是怎么被调用的

有时候,我们会在很多涉及到通过JAVA对象流进行序列化和反序列化时,会看到下面的方法: private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException 以及我们在写我们的单例类时,如果使用的不是枚举的实现

supermanL的博客 3万+

车辆网络安全ISO/SAE 21434解读(一)概述

ISO/SAE 21434 《道路车辆 网络安全工程》是SAE和ISO共同制定的一项针对道路车辆的网络安全标准,它是一个面向汽车行业全供应链(OEM及各级供应商)的车辆网络安全管理指导文件

xiaoxiabang的博客 8427

java序列化之writeObject 和readObject

什么是序列化和反序列化? 序列化:将对象转化为字节的过程称为序列化过程。 反序列化:将字节转化为对象的过程称为反序列化。 序列化主要应用于网络传输和数据存储的场景。在java中,只有类实现了java.io.serializable接口,该类才能被序列化。 示例Demo1.java: package com.example.demo; import java.io.*; public class Demo1 { public static class Person implements S

深海微澜 9944

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

深入了解序列化writeObject、readObject、readResolve

最后再总结一下java的序列化- 必须实现Serializable接口或Externalizable接口的类才能进行序列化- transient和static修饰符修饰的成员变量不会参与序列化和反序列化- 反序列化对象和序列化前的对象的全类名和serialVersionUID必须一致- 在目标类中添加私有的writeObject和readObject方法可以覆盖默认的序列化和反序列化方法。

qq_43985303的博客 2243

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

序列化writeObject与readObject

在Java中使用Serialization相当简单。如果你有一些对象想要进行序列化,你只需实现Serializable接口。然后,你可以使用ObjectOutputStream将该对象保存至文件或发送到其他主机。所有的non-transient和non-static字段都将被序列化,并且由反序列化重构造出一模一样的对象联系图(譬如许多引用都指向该对象)。但有时你可能想实现你自己的对象序列化和反序列化。那么你可以在某些特定情形下得到更多的控制。来看下面的简单例子。 class SessionDTO i

Mr_moving 1037

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

什么是writeObject 和readObject?可定制的序列化过程(转)

(对象序列化与反序列化、transient关键字) 这篇文章很直接,简单易懂。尝试着翻译一下 ,原文是What are writeObject and readObject? Customizing the serialization process. 在Java中使用Serialization相当简单。如果你有一些对象想要进行序列化,你只需实现Serializable接口。然后,

fengwen2011的博客 7743

java readobject writeobject_java – 序列化 – readObject writeObject覆盖

编写下面的代码我现在必须使用StudentData中的自定义readObject()和writeObject()覆盖方法来读取和写入对象的变量。不使用defaultWriteObject或defaultReadObject方法来执行此操作。我的代码:import java.io.*; //importing input-output filesclass Student implements ja...

weixin_36481059的博客 231

Java readObject方法分析

Java readObject方法分析 WebLogic 反序列化漏洞用到了有关 readObject 相关的知识,那么这里来分析一下 ObjectInputStream#readObject 方法,为后续 WebLogic 的反序列化漏洞分析打下基础。 编写调试类 User 类 public class User implements Serializable { private String name; private int age; protected User() thr

! 2669

Java的Serializable序列化接口的readObject和writeObject方法

以前关于readObject()和writeObject()理解不深,不明白为什么两者要是private的。网上的很多文章都直接讲它们怎么用,没有清楚阐明其道理。 这篇文章很好的回答了这个问题:http://www.javablogging.com/what-are-writeobject-and-readobject-customizing-the-serialization-process/

xiaoanian的专栏 6146

转载:什么是writeObject 和readObject?可定制的序列化过程

文章来源:https://www.iteye.com/blog/bluepopopo-486548 这篇文章很直接,简单易懂。尝试着翻译一下 ,原文是What are writeObject and readObject? Customizing the serialization process. 在Java中使用Serialization相当简单。如果你有一些对象想要进行序列化,你只需实现Serializable接口。然后,你可以使用ObjectOutputStream将该对象保存至文件或发送到其他主机

Mica_Dai的博客 364

java writeobject_java – 序列化 – readObject writeObject覆盖

编写下面的代码后,我现在必须使用自定义的readObject()和writeObject()覆盖StudentData中的方法来读取和写入对象的变量.不使用defaultWriteObject或defaultReadObject方法来执行此操作.我的代码:import java.io.*; //importing input-output filesclass Student implements...

weixin_32287387的博客 345

深入学习java源码之Object.writeObject()与Object.readObject()

深入学习java源码之Object.writeObject()与Object.readObject() 对象的输出流: ObjectOutputStream对象的输入流:  ObjectInputStream java.io.ObjectOutputStream是实现序列化的关键类,它可以将一个对象转换成二进制流,然后可以通过ObjectInputStream将二进制流还原成对象。 主要的作...

悦分享 5007

Java序列化/反序列化:readObject() 和 readResolve()的区别

Java序列化/反序列化:readObject() 和 readResolve()的区别

听海边涛声 1323
上一篇: 深入java集合学习1-集合框架浅析
下一篇: 理解Java对象序列化
天魂地煞
博客等级 码龄15年 18粉丝 36原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值