JavaSe: 不要小看了 Serializable

Java中,一个类要支持序列化,咱们一般实现Serializable。在使用Serializable,应当制定一个SerialVersionUID,用于表明类的版本。若是不指定会有什么影响呢?在了解这个以前,先来看一段exectpioon thread stack:java

 

org.apache.catalina.session.StandardManager.startInternal Exception loading sessions from persistent storage

java.io.InvalidClassException: com.bes.webgate.vo.ActiveTransactionInfoVo; local class incompatiable: stream classdesc serial versionUID =4916958502461176947, local class serialversionUID = -5826417142685217629

at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:1601)
...
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
...
at org.apache.catalina.session.StandardManager.load(StandardManager.java:162)
...

 

从上面异常来看,出现了类不兼容的问题。 到底为何呢?web

咱们就来讲说Serializable序列化的工做机制:apache

序列化的时候系统会把当前类的serialVersionUID 写入序列化的文件中(也多是其余中介),当反序列化的时候系统会去检测文件中的serialVersionUID ,看它是否和当前类的serialVersionUID 一致,若是一致就说明序列化的类的版本和当前类的版本是相同的,这个时候能够成功反序列化,不然就说明当前类和序列化的类相比发生了某些变换,好比成员变量的数量,类型可能发生了改变,这个时候就会抛异常,反序列化失败。session

那么serialVersionUID 是如何生成,生成规则是怎么样的呢?spa

默认状况下,也就是不声明serialVersionUID 属性状况下,系统会按当前类的成员变量计算hash值并赋值给serialVersionUID 。因此,结论就出来了。声明serialVersionUID ,能够很大程度上避免反序列化过程的失败。好比当版本升级后,咱们可能删除了某个成员变量,code

也可能增长了一些新的成员变量,这个时候咱们的反序列化依然可以成功,程序依然可以最大程度地恢复数据,相反,若是不指定serialVersionUID ,程序就会挂掉。blog

 

固然咱们还要考虑另一种状况,若是类结构发生了很是规性改变,好比修改了类名,类型等,这个时候尽管serialVersionUID 验证经过了,可是反序列化过程仍是会失败,由于类结构有了毁灭性的改变。hash

相关文章
相关标签/搜索