Java序列化与反序列化 Serializable 使用场景及深入认识

常见实例场景

  1. 在网络通信中:发送数据之前要序列化:send()->原始数据->序列化数据->TCP缓冲区,反之为反序列化,接收数据时候做的。
  2. Tomcat中,在服务正常关闭时候,会将session对象序列化到SESSIONS.ser文件中,下次启动重新加载到内存中
  3. Socket套接字通信中,对象在客户端与服务端传输也是通过序列化和反序列化。

 

使用场景

  1. 对象数据的持久化,因为字节序列可以比较方便地存储
  2. 在网络中序列化的字节流方便传递和接收,可以实现远程通信
  3. 在进程间通过序列化传递对象
  4. 主要是为了保存在内存中的各种对象的状态(不管成员方法),然后反序列化就是读取那些状态重做一个实例对象(有点像《三体》中三体人的脱水和复活)

 

序列化机制

Serializable接口

ObjectOutputStream.writeObject(object)

ObjectInputStream.readObject(object)

要保存到文件中的话ObjectOutputStream os = new ObjectOutputStream(FileOutputStream)

 

Externalizable接口

继承自Serializable接口

需要重写writeExternal&readExternal,用于个性化定制

需要提供一个public的无参构造器

 

进一步的认识

serialVersionUID

对序列化的对象进行版本控制,一组序列化与反序列化需要保持此值一只才能正确进行,当新类型与旧数据不兼容时,即更新版本号。

默认为“1L”,也可以根据类名、接口、方法以及属性生成一个64位的哈希字段“xxxxL”

官方文档强烈建议所有可序列化类都显式声明此值,并且使用private修饰此变量

 

静态变量的序列化

静态变量不会被序列化,因为在全局,流中没有写入静态变量。

 

transient关键字

可以控制变量序列化,在声明时加上此关键字,变量就不能被序列化到文件中,此时如果被序列化再反序列化,就会出现该变量类型的初始值,能够保障数据的安全。

 

序列化实现深克隆

序列化之后read出来,赋值给新的实例。

 

集合类的序列化

很多都在源码中重写了序列化的方法,并非完全保存了原来的集合状态,例如ArrayList的序列化和反序列话会根据集合中实际存储的元素个数操作,因为扩容机制决定了基本上容量是超出实际存储的。

 

重写方法

在序列化和反序列化过程中需要特殊处理的类必须使用三个方法的准确签名来实现特殊的方法

 

对象序列化的持久存储与保存到数据库的持久化

保存到数据库称为对象关系的映射,是将内存对象与真实数据库表中的数据进行映射绑定,而不是直接对实例对象进行了什么保存操作;序列化是对象的脱水和深拷贝。

 

Tips

  1. 父类实现序列化接口则子类自动也实现
  2. 对象的实例变量引用其他的对象,则被引用的对象也会被序列化
  3. 对于有的对象有private的域,如果进行了序列化,那么private域就不受保护了
  4. 资源分配相关的类实例,如socket,thread等,即使进行序列化,也不会将资源分配保存下来,咩有序列化的意义

 

Reference

https://www.cnblogs.com/chenbenbuyi/p/10741195.html

https://www.iteye.com/blog/xiebh-121311

https://baijiahao.baidu.com/s?id=1636492159314232573&wfr=spider&for=pc

https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值