天天看點

Java中SerialVersionUID的作用

轉載:  http://blog.sina.com.cn/s/blog_3fe961ae0100obp0.html

今天在使用eclipse開發的時候,遇到一個warning,看到warning我總覺得不爽,使用自動修複後,發現eclipse在代碼中加入了“private static final long serialVersionUID = 1L;”。其實之前就遇過這種情況了,隻是沒有去了解,于是今天我就查了一下serialVersionUID 這個變量的資訊。

原來serialVersionUID是可序列化類的一個版本辨別,在反序列化的時候使用這個辨別的值來判斷序列化和反序列化的對象類型是否一緻。Java的序列化機制是通過在運作時判斷類的serialVersionUID來驗證版本一緻性的。在進行反序列化時,JVM會把傳來的位元組流中的serialVersionUID與本地相應實體(類)的serialVersionUID進行比較,如果相同就認為是一緻的,可以進行反序列化,否則就會出現序列化版本不一緻的異常(InvalidClassException)。當你一個類實作了Serializable接口,如果沒有定義serialVersionUID,Eclipse會提供這個提示功能告訴你去定義之。 Eclipse中有兩種生成方式:

一個是預設的1L,比如:“private static final long serialVersionUID = 1L;";

一個是根據類名、接口名、成員方法及屬性等來生成一個64位的哈希字段,比如:“private static final long serialVersionUID = -8940196742313994740L;”。

使用serialVersionUID要注意以下幾點:

1.當實作java.io.Serializable接口的實體(類)沒有顯式地定義一個名為serialVersionUID,類型為long的變量時,Java序列化機制會根據編譯的class自動生成一個serialVersionUID作序列化版本比較用,這種情況下,隻有同一次編譯生成的class才會生成相同的serialVersionUID 。如果我們不希望通過編譯來強制劃分軟體版本,即實作序列化接口的實體能夠相容先前版本中未作更改的類,就需要顯式地定義一個名為serialVersionUID,類型為long的變量,不修改這個變量值的序列化實體都可以互相進行串行化和反串行化。

2.記住應該總是在可序列化的類中包含這個字段,即使是在第一個類版本中,以便提醒自己這個字段的重要性。不要在未來的版本中改變這個字段值,除非你有意要改變類使其與舊的序列化對象不相容。

3.如果你的類序列化到硬碟上面後,你更改了類别的field(增加或減少或改名),當你反序列化時,就會出現異常的,這樣就會造成不相容性的問題。但當serialVersionUID相同時,它就會将不一樣的field以type的預設值Deserialize,這個可以避開不相容性的問題。

4.當我們的系統不太經常需要序列化類時,可以去掉這些警告,做如下設定:Window-->Preferences-->Java,将serializable class without serialVersionUID的設定由warning改為Ignore。然後Eclipse會重新編譯程式,那些警告資訊也就消失了。但如果在開發大量需要序列化的類的時候,建議還原為原來的設定。這樣可以保證系統的性能和健壯。

5.更多關于可序列化對象的版本控制問題,看這裡:

http://download.oracle.com/javase/6/docs/platform/serialization/spec/version.html#6678