簡介:
簡單來說,Java的序列化機制是通過在運行時判斷類的serialVersionUID來驗證版本一致性的。在進行反序列化時,JVM會把傳來的字節流中的serialVersionUID與本地相應實體(類)的serialVersionUID進行比較,如果相同就認為是一致的,可以進行反序列化,否則就會出現序列化版本不一致的異常。
有兩種生成方式:
一個是默認的1L,比如:private static final long serialVersionUID = 1L;
一個是根據類名、接口名、成員方法及屬性等來生成一個64位的哈希字段,比如:
private static final long serialVersionUID = xxxxL;
兩種SerialVersionUid有什么區別?
add default serial version ID:
Adds a default serial version ID to the selected type
Use this option to add a user-defined ID in combination with custom serialization code if the type did undergo structural change since its first release.
add generated serial version ID:
Adds a generated serial version ID to the selected type
Use this option to add a compiler-generated ID if the type didnot undergo structural change since its first release.
兩種都可以,從JDK文檔也看不出這一點。我們只要保證在同一個類中,不同版本根據兼容需要,是否更改SerialVersionUid即可。對於第一種,需要了解哪些情況是可兼容的,哪些根本就不兼容。
參考文檔:http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf
第一種方式,在可兼容的前提下,可以保留舊版本號,如果不兼容,或者想讓它不兼容,就手工遞增版本號。
1->2->3.....
第二種方式,是根據類的結構產生的hash值。增減一個屬性、方法等,都可能導致這個值產生變化。
我想這種方式適用於這樣的場景:
開發者認為每次修改類后就需要生成新的版本號,不想向下兼容,操作就是刪除原有serialVesionUid聲明語句,再自動生成一下。
個人認為,一般采用第一種就行了,簡單。第二種能夠保證每次更改類結構后改變版本號,但還是要手工去生成,並不是修改了類,會提示你要去更新這個SerialVersionUid,所以雖然看上去很cool,實際上讓人很迷惑。
當實現java.io.Serializable接口的實體(類)沒有顯式地定義一個名為serialVersionUID,類型為long的變量時,Java序列化機制會根據編譯的class自動生成一個serialVersionUID作序列化版本比較用,這種情況下,只有同一次編譯生成的class才會生成相同的serialVersionUID ,並不穩定,這樣就可能在不同JVM環境下出現反序列化時報InvalidClassException異常。
如果我們不希望通過編譯來強制划分軟件版本,即實現序列化接口的實體能夠兼容先前版本,未作更改的類,就需要顯式地定義一個名為serialVersionUID,類型為long的變量,不修改這個變量值的序列化實體都可以相互進行串行化和反串行化。
private static final long serialVersionUID = xxxxL;
這樣就顯式的聲明了序列化實體的UID,這種方式好像是1.5才支持的(有待再核實)。
Hibernate的持久化,這個一般指的是將數據持久化到數據庫,和序列化並沒有直接關系。
Hibernate的POJO也並不要求必須實現Serializable接口,但是,作為系統擴展考慮,應該把PO都實現Serializable接口,因為如果這些對象需要緩存到磁盤上,或者在分布式環境下使用,就必須序列化,最常見的例子就是ehcache、Memcached。key和value中的對象都必須是序列化的對象。
推薦閱讀:
1.一篇較好的關於serialVesionUid的說明:
http://www.mkyong.com/java-best-practices/understand-the-serialversionuid/
2.serialVesionUid相關討論
http://stackoverflow.com/questions/888335/why-generate-long-serialversionuid-instead-of-a-simple-1l
3.compiler-generated ID生成算法
http://java.sun.com/javase/6/docs/platform/serialization/spec/class.html#4100
——————————————————
國內的coder都在抄來抄去,照搬外國的東西,這種浮躁的大環境下,大部分coder想研究一些東西也不過是心有余而力不足吧,真是悲哀。
