对象序列化(Serializable)是指将对象转换为字节序列的过程,而反序列化则是根据字节序列恢复对象的过程。
序列化一般用于以下场景:
1.永久性保存对象,保存对象的字节序列到本地文件中;
2.通过序列化对象在网络中传递对象;
3.通过序列化在进程间传递对象。
对象所属的类必须实现Serializable或是Externalizable接口才能被序列化。对实现了Serializable接口的类,其序列化与反序列化采用默认的序列化方式,Externalizable接口是继承了Serializable接口的接口,是对Serializable 的扩展,实现了Externalizable接口的类完全自己控制序列化与反序列化行为。
Java.io.ObjectOutputStream代表对象输出流,其方法writeObject(Object obj)可以实现对象的序列化,将得到的字节序列写到目标输出流中。Java.io.ObjectInputStream代表对象输入流,其 readObject()方法能从源输入流中读取字节序列,将其反序列化为对象,并将其返回。
Java的序列化机制只序列化对象的属性值,而不会去序列化什么所谓的方法。其实这个问题简单思考一下就可以搞清楚,方法是不带状态的,就是一些指令,指令是不需要序列化的,只要你的JVM classloader可以load到这个类,那么类方法指令自然就可以获得。序列化真正需要保存的只是对象属性的值,和对象的类型。
序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 可序列化类可以通过声明名为 "serialVersionUID" 的字段(该字段必须是静态 (static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID: 建议需要序列化的对象都声明自己的序列化id,因为java 默认的序列化id 的生成在 序列化方和反序列化方生成的值可能不一致。
如果序列化类的与反序列化类不一样会抛异常
java.lang.ClassCastException: com.taobao.serialize.test.DomainObject cannot be cast to com.taobao.serialize.test.DomainObject_2
如果序列化类的与反序列化类的 序列化id 不一样,则会抛异常
java.io.InvalidClassException: com.taobao.serialize.test.DomainObject; local class incompatible: stream classdesc serialVersionUID = 697337918497451172, local class serialVersionUID = 697337918497451171
只要序列化id 一样,,序列化类名一样,序列化的信息就可以反序列化回来,不会出现异常,即使是 用于序列化和反序列化的 类的 结构完全不一致也会反序列化成功
EG: