对象的序列化:把java对象转换为字节序列的过程;ObjectOutputStream.writeObject(Object obj);
对象的反序列化:把字节序列转换为java对象的过程。ObjectInputStream.readObject();
只有实现了Serializable或者Externalizable接口的对象才能被序列化。ObjectOutputStream.writeObject(Object obj)否则会抛出IOException;Externalizable继承Serializable,实现Externalizable接口的类完全由自身来控制来控制序列化的行为,而仅实现Serializable的类可以采用默认的序列化方式。JDK中如:String类,包装类,Date类实现了Serializable接口。
为了能读出正确的数据,必须保证向对象输出流写对象的顺序与从对象输入流读对象的顺序一致。
ObjectOutputStream按照默认方式序列化,仅仅对对象的非transient的实例变量进行序列化,而不会对对象的transient变量进行序列化,也不会序列化静态变量。
如果一个对象存在一对多的关联关系,那么都会序列化。
控制序列化的行为:
如果用户希望控制类的序列化,可以在序列化类中提供以下形式的writeObject()方法和readObject()方法;
private void writeObject(ObjectOutputStream out) throws IOException
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
采用自定义序列化方式的情况:
-
确保序列化的安全性,对敏感信息加密后再序列化,在反序列化的时候需要解密;
-
确保对象的成员变量符合正确的约束条件
-
优化序列化的性能。
-
便于更好的封装类的内部数据结构,确保类的接口不会被类的内部实现所束缚。
Externalizable:
Externalizable接口继承自Serializable接口,如果一个类实现了Externalizable接口,那么将完全由这个类控制自身的序列化行为,Externalizable接口声明了两个方法:
-
public void writeExternal(Objectoutput out)throws IOException ===序列化
-
public void readExternal(Objectinput in) throws IOException ClassNotFoundException ===反序列化 ,当在反序列化时,会先调用类的不带参数的构造方法,这是有别于默认反序列化方式的。
可序列化的不同版本的序列化兼容性:
凡是实现Serializable接口的类都有一个表示序列化版本标识的静态常量,private static final longserialVersionUID; serialVersionUID的取值是java运行时环境根据类的内部细节自动生成的。如果对类的源码做了修改,再重新编译,新生成的类文件的serialVersionUID的取值有可能会发生变化。
JDK 安装后,在它的bin目录下有一个serialver.exe 程序,用于查看实现了serializable接口的类的serialVersionUID。 |