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