JavaBeans
要瞭解Serializable介面之前先來瞭解最基本的JavaBeans。JavaBeans為我們提供了最簡單的Java類實體,這些實體伴隨著業務在應用中來回穿梭。JavaBeans是Java中一種特殊的類,可以將多個對象封裝到一個對象(bean)中。特點是可序列化,提供無參構造器,提供getter方法和setter方法訪問對象的屬性。名稱中的“Bean”是用於Java的可重用軟體組件的慣用叫法。
JavaBeans優點:
(1) Bean可以控制它的屬性、事件和方法是否暴露給其他程式。
(2) Bean可以接收來自其他對象的事件,也可以產生事件給其他對象。
(3) 有軟體可用來配置Bean。
(4) Bean的屬性可以被序列化,以供日後重用。
JavaBeans規範:
要成為JavaBean類,則必須遵循關於命名、構造器、方法的特定規範。有了這些規範,才能有可以使用、複用、替代和串連JavaBeans的工具。規範如下:
(1)有一個公有的無參構造器。
(2) 屬性可以通過get、set、is(可以替代get,用在布爾型屬性上)方法或遵循特定命名規範的其他方法訪問。
(3)可序列化。
JavaBean例子:
註:以上使用的是預設的serialVersionUID,會被警告,因為這樣不符合Java的效能要求。
Serializable
Java類通過實現 java.io.Serializable 介面以啟用其序列化功能。未實現此介面的類將無法使其任何狀態序列化或還原序列化。可序列化類別的所有子類型本身都是可序列化的。序列化介面沒有方法或欄位,僅用於標識可序列化的語義。要允許不可序列化類別的子類型序列化,可以假定該子類型負責儲存和還原超類型的公用 (public)、受保護的 (protected) 和(如果可訪問)包 (package) 欄位的狀態。僅在子類型擴充的類(父類)有一個可訪問的無參數構造方法來初始化該類的狀態時,才可以假定子類型有此責任。如果不是這種情況,則聲明一個類為可序列化類別是錯誤的。該錯誤將在運行時檢測到。在還原序列化過程中,將使用該類的公用或受保護的無參數構造方法初始化不可序列化類別的欄位。可序列化的子類必須能夠訪問無參數的構造方法。可序列化子類的欄位將從該流中還原。
serialVersionUID
序列化運行時使用一個稱為 serialVersionUID 的版本號碼與每個可序列化類別相關聯,該序號在還原序列化過程中用於驗證序列化對象的寄件者和接收者是否為該對象載入了與序列化相容的類。如果接收者載入的該對象的類的 serialVersionUID 與對應的寄件者的類的版本號碼不同,則還原序列化將會導致 InvalidClassException。可序列化類別可以通過聲明名為 "serialVersionUID" 的欄位(該欄位必須是靜態 (static)、最終 (final) 的 long 型欄位)顯式聲明其自己的 serialVersionUID:
如果可序列化類別未顯式聲明 serialVersionUID,則序列化運行時將基於該類的各個方面計算該類的預設 serialVersionUID 值,如“Java(TM) 對象序列化規範”中所述。不過,強烈建議 所有可序列化類別都顯式聲明 serialVersionUID 值,原因計算預設的 serialVersionUID 對類的詳細資料具有較高的敏感性,根據編譯器實現的不同可能千差萬別,這樣在還原序列化過程中可能會導致意外的 InvalidClassException。因此,為保證 serialVersionUID 值跨不同 java 編譯器實現的一致性,序列化類別必須聲明一個明確的 serialVersionUID 值。還強烈建議使用 private 修改器顯示聲明 serialVersionUID(如果可能),原因是這種聲明僅應用於立即聲明類 -- serialVersionUID 欄位作為繼承成員沒有用處。
實現java.io.Serializable 介面的類是可序列化的。沒有實現此介面的類將不能使它們的任一狀態被序列化或逆序列化。
序列化類別的所有子類本身都是可序列化的。這個序列化介面沒有任何方法和域,僅用於標識序列化的語意。允許非序列化類別的子類型序列化,子類型可以假定負責儲存和恢複父類型的公有的、保護的和(如果可訪問)包的域的狀態。只要該類(即父類)有一個無參構造子,可初始化它的狀態,那麼子類型就可承擔上述職責;如果該類沒有無參建構函式,在這種情況下申明一個可序列化的類是一個錯誤。此錯誤將在運行時被檢測。
任何類型只要實現了Serializable介面,就可以被儲存到檔案中,或者作為資料流通過網路發送到別的地方。也可以用管道來傳輸到系統的其他程式中。 提供案例
如下所示的兩個方法,都沒有問題,實質的問題在他們傳遞的SortingQualityCollection對象(JavaBean):
在程式運行時,save和update方法都可以執行成功,但是永遠返回的狀態都是false,這一點很讓人費解,在debug後發現使用Spring AOP的使用是不能夠成功的,另外最直接的錯誤是報出cglib的資源不存在。很疑惑的是,程式執行成功了update和insert的語句在後台也列印出來了,資料庫中記錄正確,由於返回的是false導致程式中業務處理始終不能往下進行。
對比過程:查看資料對象和資料庫欄位是否一致、另外JavaBean是否規範。但做完這些事情還是無濟於事,後來問題只能鎖定在JavaBean上。JavaBean是通過工具產生的,serialVersionUID如下:
於是重建serialVersionUID,新的serialVersionUID如下:
重新運行程式,程式執行成功,由此可見serialVersionUID的聲明很重要,最好在寫完JavaBean之後手動產生之,並且顯示聲明。