- 序列化带来的直接开销很是低,可是长期开销是实实在在的
实现 Serializable 接口最大的代价就是java
- 一旦一个类发布,大大下降了改变其实现的灵活性
- 由于此时,它的字节流编码就变成了其导出API的一部分
- 若是不设计一种自定义序列化形式,仅仅使用默认序列化,
- 那么私有和包级私有实例,都变成导出api的一部分
- 不符合最低限度访问域的准则
- 默认序列化可能出现新老版本序列化和反序列化不兼容
- 仔细设计一种高质量的序列化形式,长期使用,初始付出的成本是值得的
- 序列化会使得类的演变受到限制
实现 Serializable 第二个代价:api
- 增长了出现 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();//再反序列化父类的域
}