我们都知道Android对对象的序列化通常就两种方法,Serializable和Parcelable。在我们需要通过Intent和Binder传输数据和把对象持久化道存储设备上或者通过网络传输给其他客户端时,都需要使用Serializable或Parcelable来完成对象的持久化。
Serializable
Serializable是Java所提供的一个序列化接口,它是一个空接口,为对象提供标准的序列化和反序列化操作,我们使用的时候也非常简单,只需实现Serializable接口,并在类中指定类中的标识就行,如下所示:
public class A {
private static final long serialVersionUID = 123456789987654321L;
...
}
其实serialVersionUID也不是必需的,不声明serialVersionUID也不是必需的,同样可以实现序列化,但是会对反序列化过程产生影响,
serialVersionUID
serialVerisionUID是用来辅助序列化和反序列化过程的,原则上序列化后的数据中的serialVersionUID只有和当前类的serialVersionUID相同才能够正常地被反序列化。
- 工作机制:
序列化的时候系统会把当前类的serialVersionUID写入序列化的文件或其它存储介质中,当反序列化的时候系统会去检测文件中的serialVersionUID,看它是否和当前类的serialVersionUID一致,如果一致就说明序列化的类的版本和当前类的版本是相同的,则可以成功的反序列化,否则就说明当前类和序列化的类相比发生了某些变换,如成员变量的数量、类型等可能发生了变化,此时则无法正常的反序列化,会包java.io.InvalidClassException异常。
通常我们是需要手动指定serialVersionUID的值,也可以让Eclipse或AS根据当前类的结构自动生成它的hash值,这样序列化和反序列化时两者的serialVersionUID是相同的,因此可以正常进行反序列化。如果不手动指定serialVersionUID的值,反序列化时单前类有所改变,如成员变量的改变则系统会重新计算当前类的hash值并赋值给serialVersionUID,此时就和以前的serialVersionUID不一致,则反序列化失败,程序就会出现carsh。<u>所以我们手动指定serialVersionUID的话就可以尽量避免反序列化过程的失败。</u>
But,如果类结构上发生了非常规的改变,如修改类名,修改成员变量的类型,就算通过手动指定的serialVersionUID验证通过了,但是反序列化过程还是会失败,我们都知道,类结构都又了毁灭性的改变,是根本无法从老版本的数据中还原出一个新的类结构对象的。
<b>由上面我们知道,不论是手动还是工具指定的serialVersionUID,其实并没有本质的区别,效果都差不多。</b>
- 静态成员变量不属于类不属于对象,所以不需要参与序列化过程
- 用transient关键字标记的成员变量不参与序列化过程
网友评论