1. 程式人生 > >Java:關於implements Serializable的警告問題

Java:關於implements Serializable的警告問題

數據持久化 將不 invalid ror with 提示 pla ces rst

關於myeclips提示The serializable class XXX does not declare a static final serialVersionUID field of type long的警告

我們在用eclips/myeclips的時候,會出現這個warning,比如在用hibernate時,自動生成表的對應類後,就有這個提示。這是為什麽呢?

這與jdk的版本沒關系,那是Eclipse提供的功能.
你點它warning的icon兩下Eclipse就會自動給定,如果你不喜歡,可以把它關掉,
windows -> preferences -> compiler -> Error/Warnings -> Potential Programming problems
將Serializable class without serialVersionUID的warning改成ignore.

其實如果你沒有考慮到兼容性問題時,那就把它關掉吧.
其實有這個功能是好的.只要任何類別實作了Serializable這個介面,
如果沒有加入serialVersionUID,Eclipse都會給你warning提示,
這個serialVersionUID為了讓該類別Serializable後兼容.

考慮一下,如果今天你的類Serialized存到硬碟裏,
可是後來你卻更改了類別的field(增加或減少或改名).
當你Deserialize時,就會出現Exception.這樣就會做成不兼容性的問題.

但當serialVersionUID相同時,它就會將不一樣的field以type的預設值Deserialize.

這個可以避開不兼容性的問題.

================================================================

【Ohters】

對於“the serializable class XXXXXXXX does not declare a static final seriaVersionUID field of type long”的警告

系統一直會提示三種快速解決方案:

1.add default serial version ID

2.add generated serial version ID

3.add "Suppress Warnings" ‘servial‘ to XXXXXXXX

一、前言

SerialVersionUid,簡言之,其目的是序列化對象版本控制,有關各版本反序列化時是否兼容。如果在新版本中這個值修改了,新版本就不兼容舊版本,反序列化時會拋出InvalidClassException異常。如果修改較小,比如僅僅是增加了一個屬性,我們希望向下兼容,老版本的數據都能保留,那就不用修改;如果我們刪除了一個屬性,或者更改了類的繼承關系,必然不兼容舊數據,這時就應該手動更新版本號,即SerialVersionUid。

關於其定義,可參考JDK文檔:http://download.oracle.com/javase/1.5.0/docs/api/java/io/Serializable.html

二、問題

1.如果不顯式設置SerialVersionUid,有什麽後果?

jdk文檔中有解釋,建議我們顯式聲明,因為如果不聲明,JVM會為我們自動產生一個值,但這個值和編譯器的實現相關,並不穩定,這樣就可能在不同JVM環境下出現反序列化時報InvalidClassException異常。

...it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations...

2.兩種SerialVersionUid有什麽區別?

在Eclipse中,提供兩種方式讓我們快速添加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.

一種就是1L,一種是生成一個很大的數,這兩種有什麽區別呢?

看上去,好像每個類的這個類不同,似乎這個SerialVersionUid在類之間有某種關聯。其實不然,兩種都可以,從JDK文檔也看不出這一點。我們只要保證在同一個類中,不同版本根據兼容需要,是否更改SerialVersionUid即可。

對於第一種,需要了解哪些情況是可兼容的,哪些根本就不兼容。 參考文檔:http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf

在可兼容的前提下,可以保留舊版本號,如果不兼容,或者想讓它不兼容,就手工遞增版本號。

1->2->3.....

第二種方式,是根據類的結構產生的hash值。增減一個屬性、方法等,都可能導致這個值產生變化。我想這種方式適用於這樣的場景:

開發者認為每次修改類後就需要生成新的版本號,不想向下兼容,操作就是刪除原有serialVesionUid聲明語句,再自動生成一下。

個人認為,一般采用第一種就行了,簡單。第二種能夠保證每次更改類結構後改變版本號,但還是要手工去生成,並不是修改了類,會提示你要去更新這個SerialVersionUid,所以雖然看上去很cool,實際上讓人很迷惑。

參考:

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

其他相關問題:

Hibernate的持久化,這個一般指的是將數據持久化到數據庫,和序列化並沒有直接關系。

Hibernate的POJO也並不要求必須實現Serializable接口,但是,作為系統擴展考慮,應該把PO都實現Serializable接口,因為如果這些對象需要緩存到磁盤上,或者在分布式環境下使用,就必須序列化,最常見的例子就是ehcache、Memcached。key和value中的對象都必須是序列化的對象。

PS:原文地址http://hi.baidu.com/wojiubaibudu/blog/item/67aeb196eba8837e55fb968b.html

Java:關於implements Serializable的警告問題