转载请注明博客地址:http://blog.csdn.net/suileisl
1.什么是Java的序列化
序列化是对Java对象的序列化。序列化能够将对象的状态信息转化成存储或者传输的形式,例如文件或者网络流,等持久或者临时的存储区。在反序列化的时候能够读取对象的状态,并重新恢复对象。
2.为什么要进行序列化
Java对象的序列化主要是为了两个目的:1. 将对象的状态存储起来,便于使用时恢复状态;2. 用于从一个域传递到另一个域,典型的应用是对象在网络中的传输,必须对对象进行序列化。
3.序列化实现的方式
Java对象的序列化有两种方式:1. 自动化的对象序列化;2. 非自动的对象序列化;
1)自动化的对象序列化,实现Serializable接口,JVM会在序列化的时候,自动将“常规”字段进行序列化。
2)非自动的对象序列化,实现Externalizable接口,必须主动调用其中的writeExternal和readExternal方法,对对象进行序列化。
当然,Serializable接口也可以进行主动序列化指定的字段,即创建private的writeObject和readObject方法。
4.哪些属性可以实现自动序列化,哪些属性不可以实现自动序列化
1)可以进行序列化的属性:
对象的“常规”字段,而不是类的字段;即非static修饰的字段。
对象的非transient关键字修饰的字段。如果字段被这个关键字修饰,那么在自动化序列化和反序列化时,会将改字段进行忽略。常用于不想被外界看到的敏感字段。
2)用户可以通过主动调用write或者read的相关方法,主动存储那些不能被自动序列化的对象属性。
5.Java对象序列化对于同一个对象的序列化操作
Java序列化对于同一个对象的多次序列化,不会重复写入,而是采用添加引用的方式进行标记,从而降低存储的开销。
6.serialVersionUID的说明
序列化在运行时关联每一个序列化对象是通过一个版本号,也就是serialVersionUID。这个字段被用作在反序列化时,对于发送者和接收者加载序列化对象的一致性进行校验,如果不一致将会抛出InvalidClassException。该字段必须是static final long 类型的。
如果不显示的定义这个字段,JVM会生成默认值。该默认值对多因素想依赖,所以建议实现序列化接口时显示的定义该字段。并且将该字段定义为private。
另外,数组类(Array classes)不能显示的声明这个字段,JVM会生成默认值,同时,对于数组类,匹配serialVersionUID值的要求也被取消了。
关于serialVersionUID是固定的1L还是随机生成一个,我个人的观点是在常规的项目中,直接使用1L即可。
7.serialVersionUID的最佳实践
serialVersionUID的生成是与类对象的属性、方法等特征相关的。如果这些特征发生变化,则每次生成的serialVersionUID都会不同。
serialVersionUID是用来表示类对象版本的。
serialVersionUID的最佳实践主要有以下两点:
1)如果使用固定的1L,则后续升级代码,如:增加属性、方法等。当对象被反序列化时,不会抛出InvalidClassException,而是将不存在的属性或者方法调用,返回默认值(0或者null)。也就是说,如果使用升级的代码读取原始代码序列化的对象,则可能会有数据获取不到等问题。
2)如果使用生成的serialVersionUID,当增加属性、方法时,如果不重新生成serialVersionUID,则会遇到与1)同样的情况,但是不会出现异常;反之,如果每次对类的改变都重新生成serialVersionUID,则在反序列化是就会出现InvalidClassException。
综上,固定1L的方式最大程度的保证了版本的兼容性,而生成的方式则提供了对序列化对象更好的保护和访问版本控制。
关于相关的实验,请关注Java序列化机制(2)- serialVersionUID实验
作者简介
昵称:根根
姓名:隋磊
QQ:522173163
email:rsuilei@126.com
相关博客内容,离不开《至高天》系统架构师团队的支持
猫头哥:http://phl.iteye.com/
根根:http://blog.csdn.net/suileisl
芝麻的奋斗:http://sesame84.iteye.com/
wan560:http://blog.csdn.net/wan560/
terrily:http://terrily.iteye.com/