對象序列化


因爲之前面試中被問到過序列化的問題,所以今天就來整理一下關於對象序列化的知識點。

(1) 什麼是將該對象序列化?

概念:對象序列化就是將對象編碼成字節流並從字節流編碼中重新構建對象。“將一個對象編碼成一個字節流”,稱作將該對象序列化。相反的過程稱作反序列化。

(2)序列化有什麼作用?

作用:==一旦對象被序列化之後,其編碼就可以從一臺正在運行的虛擬機被傳遞到另一臺虛擬機上,或者被存儲到磁盤上,供以後反序列化時用。==序列化技術爲遠程通信提供了標準的線路級表示法,也爲javaBeans組件結構提供了標準的持久化數據格式。

(3)如何實現對象序列化?

方法:要想使一個類的實例可被序列化,只要在其聲明中加入“implements Serializable”即實現序列化接口即可。
看似實現序列化是十分容易的,但是實際上爲了實現序列化而付出的開銷往往是實實在在的。

(4)實現序列化接口付出了什麼代價?

  • 代價一:實現Serializable接口而付出的最大代價是:一旦一個類被髮布,就大大降低了“改變這個類的實現”的靈活性。
    如果一個類實現了Serializable接口,它的字節流編碼(也稱序列化形式)就變成了它的導出的API的一部分,一旦這個類被廣泛使用,往往必須永遠支持這種序列化形式。如果不是自定義的序列化形式,而選擇的是默認的序列化形式,那麼這個類中私有的和包級私有的實例域都將變成導出API的一部分,就失去了作爲信息隱藏工具的有效性。如果接受了默認和序列化形式,以後又需要改變這個類的內部表示法,結果可能導致序列化形式的不兼容。
    因此,相比較而言,設計良好的序列化形式也許會給類的演變帶來好處。
  • 代價二:增加了出現Bug和安全漏洞的可能性
    通常對象的創建時通過構造器來創建的,序列化機制是一種語言之外的對象創建機制。反序列化機制也稱“隱藏的構造器”,由於反序列化機制沒有顯示的構造器,故很容易忘記要確保:反序列化過程必須也要保證所有“由真正的構造器構造起來的約束關係”,並且不允許攻擊者訪問正在構造過程中的對象的內部信息。而依靠默認的序列化機制,很容易使對象的約束關係遭到破壞,以及遭受到非法訪問。
  • 代價三:隨着類發行新的版本,相關的測試負擔也增加了
    當一個可序列化的類被修訂的時候,很重要的一點是,要檢查是否可以“在新版本中序列化一個實例,然後在舊版本中反序列化”,反之亦然。

(5)transient

transaction修飾符表明您這個實例域將從一個類的默認序列化形式中省略掉,可以加在類某個屬性上,表示序列化時將該屬性排除在外。

(6)反序列化默認值

當一個實例被反序列化的時候,其域被初始化爲它的默認值:對於對象引用域,默認爲null;對於數值基本域,默認爲0;對於Boolean類型,默認爲false。

(7)UID

  • 序列化會使類的演變受到限制,這種限制的一個例子與流的唯一標識符有關,通常它也被稱爲序列版本UID。
  • 每個可序列化的類都有唯一一個標識符與它相關聯,如果你沒有在一個名爲serialversionUID的私有靜態final的long域中顯示的產生該標識號,系統將會自動地根據這個類來調用一個複雜的運算過程,從而在運行的時候產生該標識號。
  • 這個自動產生的值,受到類的名稱,它所實現的接口的名稱,以及所有的公有的和受保護的成員的名稱所影響。
  • 如果通過任何方式改變了這些信息,自動產生的UID也會發生變化。無論選擇哪種序列化形式。,都要爲自己編寫的每個可序列化的類聲明一個顯示的序列化版本UID,這樣可以避免序列版本UID成爲潛在的不兼容根源。而且也可避免在運行時通過一個高開銷的計算過程產生一個序列版本UID,提高性能。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章