【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
- 序列化带来的直接开销非常低,但是长期开销是实实在在的
实现 Serializable 接口最大的代价就是
- 一旦一个类发布,大大降低了改变其实现的灵活性
- 因为此时,它的字节流编码就变成了其导出API的一部分
- 如果不设计一种自定义序列化形式,仅仅使用默认序列化,
- 那么私有和包级私有实例,都变成导出api的一部分
- 不符合最低限度访问域的准则
- 默认序列化可能出现新老版本序列化和反序列化不兼容
- 仍然保留老接口,会带来别的问题、隐患
- 仔细设计一种高质量的序列化形式,长期使用,初始付出的成本是值得的
- 序列化会使得类的演变受到限制
- 流的唯一标识符有关(序列版本UID)
-
private static final long serialVersionUID = 1L;
- 如果不定义该标识符,会在运行时,调用一个复杂的过程自动生成
- 而且内部改变,会导致,自动计算id 值改变,序列化兼容被打破
- 导致InvalidClassException
- 而且内部改变,会导致,自动计算id 值改变,序列化兼容被打破
-
- 流的唯一标识符有关(序列版本UID)
实现 Serializable 第二个代价:
- 增加了出现 BUG、安全漏洞的可能性
- 对象是构造器创建的
- 序列化机制是语言之外的对象创建机制
- 反序列化机制都是一个隐藏的构造器
- 该构造器相对于真正的构造器,约束条件往往被忽略
- 默认序列化机制的反序列化过程的约束关系很容易遭到破坏、非法访问
- 反序列化机制都是一个隐藏的构造器
第三个代价:
- 随着类发行新的版本、相关测试负担也增加了
- 一个可序列化的类被修订后,要检查,在新版本序列化一个类,在老版本是否可以反序列化,反之亦然
- 测试工作量乘积增长
实现Serializable 确实带来了益处:
- 比如一些值类:Date、BigInteger 可以实现Serializable
- 活动实体类:Thread pool 一般不实现Serializable
为了继承而设计的类、接口,尽可能少的实现 Serializable 接口
- 但是如果专门设计参与到某个框架的类,该框架要求必须实现Serializable 时例外
- 为了继承而设计的类,实现了Serializable 接口的有
- Throwable类:RMI异常,可以从服务端传到客户端
- Component :GUI 可以被发送保存和恢复
- HttpServlet抽象类:会话状态可以被缓存
- 如果实现带有实例域的类,实例域被初始化成默认值会违背约束条件
- 就必须添加下文中的方法
如果一个专门为了继承而设计的类不是可序列化的,
- 就不可能编写出可序列化的子类。
- 特别是,如果超类没有提供可访问的无参构造器,子类也不可能做到可序列化。
- 因此,对于为继承而设计的不可序列化的类,你应该考虑提供一个无参构造器。
内部类不应该实现Serializable。
- 它们使用编译器产生的合成域来保存指向外围实例的引用,
- 以及保存来自外围作用域的局部变量的值。
- 因此,内部类的默认序列化形式是定义不清楚的。
- 然而,静态成员类却是可以实现Serializable接口。
千万不要认为实现Serializable接口会很容易。
- 除非一个类在用了一段时间之后就会被抛弃,
- 否则,实现Serializable接口就是个很严肃的承诺,必须认真对待。
- 如果一个类是为了继承而设计的,则更加需要加倍小心。
- 对于这样的类而言,在“允许子类实现Serializable接口”或“禁止子类实现Serializable接口”两者之间的一个折衷设计方案是,
- 提供一个可访问的无参构造器,这种设计方案允许(但不要求)子类实现Serializable接口。
- 至于为什么需要父类有一个无参的构造器,
- 是因为子类先序列化自身的时候先调用父类的无参的构造器。
- 实例:
-
private void writeObject(java.io.ObjectOutputStream out) throws IOException{ out.defaultWriteObject();//先序列化对象 out.writeInt(parentvalue);//再序列化父类的域 } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{ in.defaultReadObject();//先反序列化对象 parentvalue=in.readInt();//再反序列化父类的域 }
-
- 对于这样的类而言,在“允许子类实现Serializable接口”或“禁止子类实现Serializable接口”两者之间的一个折衷设计方案是,
来源:oschina
链接:https://my.oschina.net/u/3847203/blog/3010010