Serialization 簡單小結

 
I. 什麼是對象序列化
 
1. 我們要把對象保存到硬盤或者通過網絡傳輸,就需要把對象狀態保存下來,這個過程就是對象序列化或串行化。Java 中的序列化機制能夠將一個實例對象的狀態信息寫入到一個字節流中,使其可以通過socket進行傳輸、或者持久化存儲到數據庫或文件系統中;然後在需要的時候,可以根據字節流中的信息來重構一個相同的對象。
2.對象序列化不是簡單的把內存的內容拷貝出來。至少有下面的一些原因。
i. 如果對象還引用了其它對象,則引用的對象也需要保存下來。這時只是簡單的保存引用對象的地址是沒有意義的。這個地址只是在程序運行時纔有意義,程序結束了無法根據地址找到引用對象的狀態。這個過程是遞歸的,因爲我們可能需要保存對象的對象的對象。
ii. 如果我們在不同系統之間使用同一個對象,比如把對象從windown傳輸到linux系統。這時對象應該以通用的形式保存或傳輸,異構系統才能知道如何恢復對象的狀態而不必關心其它系統的實現細節。
 
II. Java怎樣序列化

1.Java語言中,對象要能被序列化,需要實現Serialization。這個接口沒有任何方法,只是一個標誌性接口,表明這個對象可以被序列化。使用ObjectOutputStream的writeObject方法序列化一個對象;使用ObjectInputStream的readObject方法反序列化一個對象。

2.Java的序列化機制是通過在運行時判斷類的serialVersionUID來驗證版本一致性的。在進行反序列化時,JVM會把傳來的字節流中的serialVersionUID與本地相應實體(類)的serialVersionUID進行比較,如果相同就認爲是一致的,可以進行反序列化,否則就會出現序列化版本不一致的異常。需要序列化的對象應該顯示的定義一個serialVersionUID,利用JDK的bin目錄下的serialver.exe可以產生UID。如果沒有顯示定義,Java序列化機制會自動生成一個serialVersionUID,這種情況下,只有同一次編譯生成的class纔會生成相同的serialVersionUID.

3. 序列化對象時,對象裏引用的對象也要被序列化,但這個前提是引用的對象能被序列化。如果引用的對象不能被序列化,序列化終止,拋出NotSerializableException的異常。可以把不能序列化的引用的對象標誌位transient。
4. 父類不能序列化,但是子類可以序列化,只要子類實現Serializable接口。這種情況,在反序列化時,父類必須提供默認參數,否則會報InvalidClassException異常。這也好理解。恢復一個對象,就是恢復其所有成員變量的值,而父類的成員變量的值不能恢復,就調用默認構造函數來初始化。

 

III. 自定義序列化過程

1. 如果不想使用Java提供的默認序列化方法(ObjectOutputStream的defaultWriteObject)或者反序列化方法(ObjectInputStream的defaulReadObject),則可以在需要序列化的類中實現writeObject或者readObject方法。
 
2. 可以實現Externalizable接口來完全控制序列化和反序列化過程和形式。
 
IV.避免序列化
1. 對象序列化時,任何方法和靜態變量時不能被保存的。如果有些字段,比如密碼,不需要被序列化,就用transient關鍵字標示這個字段。
 
2. 如果一個類不需要序列化,肯定是不實現Serializable接口。但是,如果這個類繼承了一個可以序列化的類,這個類默認是可以序列化的,如果要阻止其被序列化,要麼把所有的成員變量標誌爲transient, 要麼就實現writeObject 和 readObject方法(實現它們,但它們是空辦法),並且拋出NotSerializableException異常。
 
 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章