1. 程式人生 > >JAVA 序列化 和 反序列化 (Externalizable Serializable) 那些事

JAVA 序列化 和 反序列化 (Externalizable Serializable) 那些事

序列化控制

  • 當我們對序列化進行控制時,可能某個特定子物件不想讓Java序列化機制自動儲存與恢復。如果子物件表示的是我們不希望將其序列化的敏感資訊(如密碼),通常會面臨這種情況。即使物件中的這些資訊是private屬性,一經序列化處理,人們就可以通過讀取檔案或者攔截網路傳輸的方式來訪問到它。有兩種辦法可以防止物件的敏感部分被序列化:

    • 實現Externalizable代替實現Serializable介面來對序列化過程進行控制,Externalizable繼承了Serializable介面,同時增添了兩個方法:writeExternal()readExternal()

    兩者在反序列化時的區別
    - 對Serializable物件反序列化時,

    由於Serializable物件完全以它儲存的二進位制位為基礎來構造,因此並不會呼叫任何建構函式,因此Serializable類無需預設建構函式,但是當Serializable類的父類沒有實現Serializable介面時,反序列化過程會呼叫父類的預設建構函式,因此該父類必需有預設建構函式,否則會拋異常。
    - 對Externalizable物件反序列化時,會先呼叫類的不帶引數的構造方法,這是有別於預設反序列方式的。如果把類的不帶引數的構造方法刪除,或者把該構造方法的訪問許可權設定為private、預設或protected級別,會丟擲java.io.InvalidException: no valid constructor
    異常,因此Externalizable物件必須有預設建構函式,而且必需是public的。
    Externalizable的替代方法:如果不是特別堅持實現Externalizable介面,那麼還有另一種方法。我們可以實現Serializable介面,並新增writeObject()readObject()的方法。一旦物件被序列化或者重新裝配,就會分別呼叫那兩個方法。也就是說,只要提供了這兩個方法,就會優先使用它們,而不考慮預設的序列化機制。

    這些方法必須含有下列準確的簽名:

    private void writeObject(ObjectOutputStream stream) 
            throws
    IOException; private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException


    - 可以用transient關鍵字逐個欄位地關閉序列化,它的意思是“不用麻煩你儲存或恢復資料—我自己會處理的”。由於Externalizable物件在預設情況下不儲存它們的任何欄位,所以transient關鍵字只能和Serializable物件一起使用。