序列化(Serialization)


java.io.Serializable 根 據 JDK API Docs 內的說明:

序列化運行時使用一個稱為 serialVersionUID 的版本號與每個可序列化類別相關聯,該序列號在反序列化過程中用於驗證序列化物件的發送者和接收者是否為該物件載入了與序列化相容的類別。如果接收者載入 的該物件的類別的 serialVersionUID 與對應的發送者的類別的版本號不同,則反序列化將會導致 InvalidClassException。 可序列化類別可以通過宣告名為 "serialVersionUID" 的欄位(該欄位必須是靜態 (static)、最終 (final) 的 long 型欄位)顯式宣告其自己的 serialVersionUID:

 ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
如果可序列化類別未顯式宣告 serialVersionUID,則序列化運行時將基於該類別的各個方面計算該類別的預設 serialVersionUID 值,如“Java(TM) 物件序列化規範”中所述。不過,強烈建議 所有可序列化類別都顯式宣告 serialVersionUID 值,原因是計算預設的 serialVersionUID 對類別的詳細資訊具有較高的敏感性,根據編譯器實作的不同可能千差萬別,這樣在反序列化過程中可能會導致意外的 InvalidClassException。 因此,為保證 serialVersionUID 值跨不同 java 編譯器實作的一致性,序列化類別必須宣告一個明確的 serialVersionUID 值。還強烈建議使用 private 修飾符顯示宣告 serialVersionUID(如果可能),原因是這種宣告僅應用於直接宣告類別 -- serialVersionUID 欄位作為繼承成員沒有用處。陣列類別不能宣告一個明確的 serialVersionUID,因此它們總是具有預設的計算值,但是陣列類別沒有比對 serialVersionUID 值的要求。
案例:
當一個類實現了序列化接口,有時會遇到 java.io.InvalidClassException 異常出現:
java.io.InvalidClassException: com.test.Test; local class incompatible: stream classdesc serialVersionUID = 7981560250804078637, local class serialVersionUID = -8334405535174160822
這是序列化兼容性所致;
java通過一個名為UID(stream unique identifier)來控制,這個UID是隱式的,它通過類名,方法名等諸多因素經過計算而得,理論上是一一映射的關係,也就是唯一的。如果UID不一 樣的話,就無法實現反序列化了,並且將會得到InvalidClassException。
當要人為的產生一個新的版本(實現並沒有改動),而拋棄以前的版本的話,可以通過顯式的聲名UID來實現:
private static final long serialVersionUID=????;//(你可以編造一個UID,但不能有重複)

對於上例我們可以在com.test.Test類中加入 :
private static final long serialVersionUID=7981560250804078637l;
這樣就解決了新老版本的兼容性問題。


最佳方式:

如果你能掌控類之 間的差異,就讓

private static final long serialVersionUID=-1

就行的,省得讓 Java 自己生成,或者用命令 serialver.exe 來生成 serialVersionUID
Comments