Java的序列化和反序列化

1.序列化是幹什麼的?

簡單說就是爲了保存在內存中的各種對象的狀態,

也就是實例變量,不是方法,

並且可以把保存的對象狀態再讀出來。

雖然你可以用你自己的各種各樣的方法來保存object states,

但是Java給你提供一種應該比你自己好的保存對象狀態的機制,那就是序列化。

2.什麼情況下需要序列化

當你想把的內存中的對象狀態保存到一個文件中或者數據庫中時候;
當你想用套接字在網絡上傳送對象的時候;
當你想通過RMI傳輸對象的時候;
3.一個例子

序列化需要實現Serializable或者Externalizable 接口

下面的是實現Serializable接口,最後會提到Externalizable

Java的序列化和反序列化

Java的序列化和反序列化

Java的序列化和反序列化

4.使用transient

在一些特殊場景下,比如銀行賬戶對象,出於保密考慮,

不希望對存款金額進行序列化。或者類的一些引用類型的成員是不可序列化的。

此時可以使用transient關鍵字修飾不想被或者不能被序列化的成員變量。

需要注意的是transient只能修飾屬性(filed),不能修飾類或方法。

一個靜態變量不管是否被transient修飾,均不能被序列化。

5.自定義序列化

transient提供了一種簡潔的方式將被transient修飾的成員屬性完全隔離在序列化機制之外。

這樣子固然不錯,但是Java還提供了一種自定義序列化機制讓開發者更自由地控制如何序列化各個成員屬性,

或者不序列化某些屬性(與transient效果相同)。

5.1 writeObject和readObject

Java的序列化和反序列化

這兩個方法和ObjectOutputStream及ObjectInputStream裏對應的方法名稱相同。

實際上,儘管這兩個方法是private型的,但是仍然是在被序列化(或反序列化)階段被外部類ObjectOutputStream(或ObjectInputStream)調用。

僅以序列化爲例:

ObjectOutputStream在執行自己的writeObject方法前會先通過反射在要被序列化的對象的類中

查找有無自定義的writeObject方法,

如有的話,則會優先調用自定義的writeObject方法。

因爲查找反射方法時使用的是getPrivateMethod,

所以自定以的writeObject方法的作用域要被設置爲private。

通過自定義writeObject和readObject方法可以完全控制對象的序列化與反序列化。

Java的序列化和反序列化

Java的序列化和反序列化

Java的序列化和反序列化

5.2 writeReplace和readResolve

writeReplace和readResolve是一種更徹底的序列化的機制,

它甚至可以將序列化的目標對象替換爲其它的對象。

但是與writeObject和readObject不同的是,

這二者不是必須要一起使用的,而且儘量應分開使用。

若一起使用的話,只有writeReplace會生效。

6.使用Externalizable

一開始有提到過實現Externalizable接口也可以實現類的序列化。

使用這種方法,可以由開發者完全決定如何序列化和反序列化目標對象。

Externalizable接口提供了writeExternal和readExternal兩個方法。

實際上這種方法和前面的自定義序列化方法很相似,

只是Externalizable強制自定義序列化。

在使用了Externalizable的類中仍可以使用writeReplace和readResolve方法。

使用Externalizable進行序列化較之使用Serializable性能略好,但是複雜度較高。
**學習Java的同學注意了!!!
學習過程中遇到什麼問題或者想獲取學習資源的話,歡迎加入Java學習交流羣,羣號碼:521352947 我們一起學Java!**

發佈了34 篇原創文章 · 獲贊 2 · 訪問量 6466
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章