序列化控制
- 當我們對序列化進行控制時,可能某個特定子對象不想讓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
關鍵字逐個字段地關閉序列化,它的意思是“不用麻煩你儲存或恢複資料—我自己會處理的”。由于Externalizable對象在預設情況下不儲存它們的任何字段,是以transient關鍵字隻能和Serializable對象一起使用。transient
- 實作