使用java以来序列化随处可见至于为什么要用序列化序列化能解决什么问题作为一个普通的码农一般不怎么会去深入研究由于最近在看mina和公司内部涉及到nio框架的一些源码里面涉及到hessionjava这两种序列化至于hession序列化为什么会诞生以及在apache项目中使用如此广泛以及java本身序列化存在哪些缺陷甚是不解为了解答上面抛出来的疑惑以及进一步了解java的序列化机制这里开个小头从java的序列化接口Serializable开始说起
jdk包里的Serializable接口的注释主要说明了以下几点
类通过实现Serializable接口来启用序列化否则该类的任何状态将无法被序列化同时也无法用于反序列化
若继承的父类没有实现Serializable接口但是又想让子类可序列化有三个注意事项
a)子类实现Serializable接口
b)子类必须有可访问的无参构造方法用于保存和恢复父类的public或protected或同包下的package字段的状态否则在序列化或反序列化时会抛出RuntimeException异常
c)对于序列化后的子类在进行反序列化时理论上无法初始化父类中private(不可访问)对象变量的状态或值
在对可序列化类中的属性进行序列化时如果遇到不可序列化的对象变量此时会针对不可序列化的类抛出NotSerializableException异常
对于可序列化的非数组类强烈建议显示声明static型long型final型serialVersionUID字段用于标识当前序列化类的版本号否则在跨操作系统跨编译器之间进行序列化和反序列化时容易出现InvalidClassException异常
对于可序列化类中的statictransient对象变量在序列化时无法保存其状态或值static对象变量在反序列化时取得的值为当前jvm中对应类中对应static变量的值而transient(瞬态)关键字则一般用于标识那些在序列化时不需要传递的状态变量
简单的测试代码
import javaioFileInputStream import javaioFileNotFoundException import javaioFileOutputStream import javaioIOException import javaioObjectInputStream import javaioObjectOutputStream import javaioSerializable
/** * 序列化测试 * * @author sume * */ public class SerializableImpl implements Serializable {
private static final long serialVersionUID = L
static String staticVal = static transient String transientVal = transient String val = val
/** * main */ public static void main(String[] args) throws FileNotFoundException IOException ClassNotFoundException { // 序列化 SerializableImpl sila = new SerializableImpl() ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(Serializabletxt)) objectOutputStreamwriteObject(sila) objectOutputStreamclose()
// 反序列化 SerializableImplstaticVal = static ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Serializabletxt)) SerializableImpl sila = (SerializableImpl) objectInputStreamreadObject() objectInputStreamclose()
// 比较各个属性的值 Systemoutprintln(silastaticVal) Systemoutprintln(silatransientVal) Systemoutprintln(silaval) } }输出结果 static null val从输出结果可以看出
反序列化后类中static型变量staticVal的值为当前jvm中对应static变量的值为static而不是序列化时的值static
transient关键字标识的变量的状态并没有在序列化中被保存因此反序列化后
transientVal变量的值为null
第三个为常见的对象状态在序列化和反序列化过程中的传递
简单印证了前面所说的几点内容