天天看點

Java序列化機制中的類版本号問題

内容簡單介紹

某些實作了serializable接口的java類中會看到名稱為serialVersionUID的靜态字段,本文從根本上解釋這個字段的含義。

知識鋪墊

在java中,類的序列化和反序列化是由jvm實作,當然,不同的jvm可能有不同的實作方式,本文讨論java官方的jvm版本号。

一個類,實作serializable接口之後,就代表開發人員同意此類能夠被序列化和反序列化,jvm就獲得了序列化和反序列化此類的授權。假設沒有實作serializable,而直接進行類的序列化操作,jvm會報出異常。

Serializable是一個辨別接口,沒有不論什麼待實作的方法。

概念

Java序列化機制使用名稱為serialVersionUID的long型字段來标志類的版本号。序列化對象時,Jvm會把serialVersionUID的值寫到類的序列化資料中;反序列化時,JVM會把對象資料資料中的serialVersionUID與本地對應類的serialVersionUID進行比較,假設值不同樣(意味着類的版本号不同),那麼報異常InvalidCastException,即:類版本号不正确應,不能進行反序列化。假設類版本号同樣,則能夠進行反序列化。

常見的serialVersionUID的值有兩種情況:        

一種是固定的一個long型值,比方:

private static final  long  serialVersionUID = 1L;  

private static final  long  serialVersionUID = 123L;  

另外一種是依據類名、接口名、成員方法及屬性等生成一個64位的哈希值(ide能夠完畢此工作),比方:

private static final  long  serialVersionUID = xxxxL; 

當實作java.io.Serializable接口的類沒有顯式地定義一個serialVersionUID值時,Java序列化機制會依據編譯的Class生成一個serialVersionUID作序列化版本号比較用,一旦class檔案有所變動(比方空格、變量名),那麼serialVersionUID也會随之變動。

序列化資料和類版本号同樣但結構不同

當一個類和它的序列化資料的版本号同樣(即serialVersionUID值同樣),但類結構不同一時候,反序列化過程遵循下面規則。