概述
- 序列化:将对象写入到
IO
流中 - 反序列化:从
IO
流中恢复对象
实现方法
实现 Serializable
或者 Externalizable
Serializable
:标记接口,不用实现任何方法,可以指定序列化ID
Externalizable
:增强的序列化标记接口,提供了writeExternal
和readExternal
两个接口方法,这两个方法在序列化和反序列化的过程中会被调用
注意,序列化 ID
只是一个版本号,两种方法都可以不指定,JVM
会根据类中的信息自动计算一个序列化版本号。不指定序列化版本号可能存在如下隐患:
- 不同版本的
JVM
可能会有不同的计算规则,可能会导致类的信息完全一致但是序列化失败 - 在类中的信息被修改后,由于
JVM
计算出来了不同的版本号,则很可能导致序列化失败
Serializable 和 Externalizable 的区别
- 实现
Serializable
不用额外实现方法,但是实现Externalizable
必须实现writeExternal
和readExternal
两个方法 - 实现
Externalizable
必须要提供public
修饰的无参构造器,否则会报错;Serializable
不需要无参构造器 - 实现
Externalizable
必须把所有需要序列化的属性在writeExternal
中一一手动序列化,所有需要反序列化的属性在readExternal
中一一手动反序列化;Serializable
由JVM
自动完成
Serializable 的扩展点
- 可以实现
private void writeObject(ObjectOutputStream out)
来自定义序列化逻辑,注意必须使用完全一致的方法名和private
修饰符 - 可以实现
private void readObject(ObjectInputStream in)
来自定义反序列化逻辑,注意必须使用完全一致的方法名和private
修饰符 - 当某个属性上加上了
transient
关键字后,这个属性将不会被序列化
注意点
- 当一个序列化对象存在一个引用类型的对象时,这个对象也必须是可实例化的(或者加上
transient
关键字),否则会报错 - 同一对象只会被序列化成二进制流一次,不会重复序列化
- 单例类被序列化时,需要重写
readResolve
方法,否则会破环单例机制