一个类实现了Serializable 接口,并且使用了默认的序列化形式
- 无法摆脱该实现,永远牵制该类的序列化形式
如果没有认真考虑默认序列化形式是否合适,不要贸然接受
如果一个对象的物理表示法等同于逻辑内容,可能就适合于默认序列化形式
- 默认序列化,必须提供一个readObject 方法,来保证约束关系和安全性
如果一个对象的物理表示法与逻辑内容存在实质性区别时,默认序列化存在4个缺点:
- 该类导出API 永远束缚在该类的内部方表示法上
- 不方便以后扩展
- 消耗过多空间
- 消耗过多时间
- 会引起栈溢出
- 默认序列化会对对象图进行一次递归遍历,很容易栈溢出
redaObject 和writeObject
- 实现这俩参数时,默认调用super.defaultReadObject 和 super.defaultWriteObject
- 如果所有成员变量都是transient(瞬时的),技术上不调用问题不大
- 但是还是推荐调用下
- 但是不调用灵活性大增
散列表的序列化
- 同一JVM无法保证每次运行都一样
- 因此默认序列化会到来严重的bug
- 散列表的序列化和反序列化产生的对象,约束关系严重破坏
无论是否使用默认序列化形式
- 调用defaultWriteObject方法,transient实例域 都会被序列化
transient 域反序列化后会初始化默认值
- 如果不能被任何任何transient域所接受,
- 可以实现redaObject 调用defaultReadObject 恢复为可接受的域
- 也可以将这些域延时到第一次被使用才真正初始化
无论何种序列化形式,如果读取整个对象状态的任何其他方法上强制任何同步,
- 必须在对象序列化上强制这种同步
- 线程安全性考虑
- 注意锁的使用,规避资源排列死锁的危险
- 声明显式的序列化UID
- 这样避免序列化版本成为潜在不兼容根源
- 而且如果没有显式UID,会高成本产生一个序列化UID
- 如果希望新版本能够接受现有序列化实例,就必须使用之前生成的旧版本UID
- 想要与现有版本不兼容,修改序UID即可
- 前版本实例反序列化会引发 InvalidClassException异常