Serializable和Externalizable

纯粹是个人学习总结,如有不对的地方请吐槽。

“对象序列化”(Object Serialization)是 Java1.1就开始有的特性。 简单地说,就是可以将一个对象(标志对象的类型)及其状态转换为字节码,保存起来(可以保存在数据库,内存,文件等),然后可以在适当的时候再将其状态恢复(也就是反序列化)。serialization 不但可以在本机做,而且可以经由网络操作。它自动屏蔽了操作系统的差异,字节顺序等。比如,在 Windows 平台生成一个对象并序列化之,然后通过网络传到一台 Unix 机器上,然后可以在这台Unix机器上正确地重构(deserialization)这个对象。 不必关心数据在不同机器上如何表示,也不必关心字节的顺序或者其他任何细节。

  1. java.io.Serializable接口没有任何方法属性域,实现它的类只是从语义上表明自己是可以序列化的。

  2. 在对一个 Serializable(可序列化)对象进行重新装配的过程中,不会调用任何构建器(甚至默认构建器)。整个对象都是通过从 InputStream 中取得数据恢复的。

  3. 如是要一个类是可序列化的,那么它的子类也是可序列化的。

只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以采用默认的序列化方式。

特殊情况-父类不可序列化而子类可序列化

我们看到,对于B的属性b1,其可以正确的序列化,但对于其从A继承过来的属性a,b则没有正确的序列化。为什么呢?我们再看上面的运行结果,可以发现:反序列化的时候,由于B实现了Serializable,所在以反序列化的时候,它并不会调用它自己的构造器,但是,在反序列化B的时候,却调用了它的超类的构造器(实际上不仅仅是构造器,A的所有的初始化过程都会正常进行)。这正是上面结果中a,b的值没有正确反序列化的原因。

于是,对于这种父类非序列化而子类可序列化的类,子类应该自己对超类的public,protected,以及 friedly 属性进行单独处理。

方法是不带状态的,就是一些指令,指令是不需要序列化的,只要你的JVM classloader可以load到这个类,那么类方法指令自然就可以获得。序列化真正需要保存的只是对象属性的值,和对象的类型。

请记住序列化机制只保存对象的类型信息,属性的类型信息和属性值,和方法没有什么关系,你就是给这个类增加10000个方法,序列化内容也不会增加任何东西,不要想当然的臆测自己不了解的知识,动手去做!

序列化在 Effective Java 中讲得很清楚啊, 一般认为只声明实现 implements 接口, 不提供自定义的序列化形式是不负责任的做法, 这样可能导致比较多的问题比如类的不同版本之间的兼容性, 看看 Effective Java 中的条目吧

谨慎地实现 Serialiable

为了继承而设计的类应该很少实现 Serialiable, 接口也应该很少会扩展它. 如果违反了这条规则, 则扩展这个类或者实现这个接口的程序员会背上沉重的负担.

若没有认真考虑默认序列化形式是否合适, 则不要接受这种形式

即使你确定了默认序列化形式是合适的, 通常你仍然要提供一个 readObject方法以保证约束关系和约束性

不管你选择了哪种序列化形式, 你都要为自己编写的每个可序列化的类声明一个显式的序列版本 UID (serialVersionUID)

原文地址:http://www.cnblogs.com/davidwang456/p/3932025.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值