Effective Java之谨慎地实现Serializable(七十四)

1.序列化的含义和作用

序列化用来将对象编码成字节流,反序列化就使将字节流编码重新构建对象。
序列化实现了对象传输和对象持久化,所以它能够为远程通信提供对象表示法,为JavaBean组件提供持久化数据。

2.序列化的危害

1.降低灵活性:为实现Serializable而付出的最大代价是,一旦一个类被发布,就大大降低了”改变这个类的实现”的灵活性。如果一个类实现了Serializable,它的字节流编码(或者说序列化形式,serialized form)就变成了它的导出的API的一部分,必须永远支持这种序列化形式。

而且,特殊地,每个可序列化类都有唯一的标志(serial version id,在类体现为私有静态final的long域serialVersionUID),如果没有显式指示,那么系统就会自动生成一个serialVersionUID,如果下一个版本改变了这个类,那么系统就会重新自动生成一个serialVersionUID。因此如果没有声明显式的uid,会破坏版本之间的兼容性,运行时产生InvalidClassException。

2.降低封装性:如果你接受了默认的序列化形式,这个类中私有的和包级私有的实例域将都变成导出的API的一部分,这不符合”最低限度地访问域”的实践准则。

3.降低安全性:增加了bug和漏洞的可能性,反序列化的过程其实类似于调用对象的构造器,但是这个过程又没有用到构造器,因此如果字节流被无意修改或被用心不测的人修改,那么服务器很可能会产生错误或者遭到攻击。

16年出现的大名鼎鼎的Java反序列化漏洞本质上就是不恰当的序列化造成的。

4.降低可测试性:随着类版本的不断更替,必须满足版本兼容问题,所以发行的版本越多,测试的难度就越大。

5.降低性能:序列化对象时,不仅会序列化当前对象本身,还会对该对象引用的其他对象也进行序列化。如果一个对象包含的成员变量是容器类等并深层引用时(对象是链表形式),此时序列化开销会很大,这时必须要采用其他一些手段处理。

3.序列化的使用场景

1.需要实现一个类的对象传输或者持久化。
2.A是B的组件,当B需要序列化时,A也实现序列化会更容易让B使用。

4.序列化不适合场景

为了继承而设计的类应该尽可能少地去实现Serializable接口,用户接口也应该尽可能不继承Serializable接口,原因是子类或实现类也要承担序列化的风险。

5.序列化需要注意的地方

1)如果父类实现了Serializable,子类自动序列化了,不需要实现Serializable;

2)若父类未实现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();//再反序列化父类的域 
  } 

3)序列化时,只对对象状态进行了保存,对象方法和类变量等并没有保存,因此序列化并不保存静态变量值。

4)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象序列化了。所以组件也应该序列化。

5)不是所有对象都可以序列化,基于安全和资源方面考虑,如Socket/thread若可序列化,进行传输或保存,无法对他们重新分配资源。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值