考慮自定義的序列化模式(75)

一個類實現了Serializable 接口,而且使用了默認的序列化形式安全

  • 沒法擺脫該實現,永遠牽制該類的序列化形式

若是沒有認真考慮默認序列化形式是否合適,不要貿然接受線程

若是一個對象的物理表示法等同於邏輯內容,可能就適合於默認序列化形式對象

  • 默認序列化,必須提供一個readObject 方法,來保證約束關係和安全性

若是一個對象的物理表示法與邏輯內容存在實質性區別時,默認序列化存在4個缺點:遞歸

  1. 該類導出API 永遠束縛在該類的內部方表示法上
    • 不方便之後擴展
  2. 消耗過多空間
  3. 消耗過多時間
  4. 會引發棧溢出
    • 默認序列化會對對象圖進行一次遞歸遍歷,很容易棧溢出

redaObject 和writeObject接口

  • 實現這倆參數時,默認調用super.defaultReadObject 和 super.defaultWriteObject
    • 若是全部成員變量都是transient(瞬時的),技術上不調用問題不大
    • 可是仍是推薦調用下
    • 可是不調用靈活性大增

散列表的序列化資源

  • 同一JVM沒法保證每次運行都同樣
  • 所以默認序列化會到來嚴重的bug
  • 散列表的序列化和反序列化產生的對象,約束關係嚴重破壞

不管是否使用默認序列化形式同步

  • 調用defaultWriteObject方法,transient實例域 都會被序列化

transient 域反序列化後會初始化默認值it

  • 若是不能被任何任何transient域所接受,
    • 能夠實現redaObject 調用defaultReadObject 恢復爲可接受的域
    • 也能夠將這些域延時到第一次被使用才真正初始化

不管何種序列化形式,若是讀取整個對象狀態的任何其餘方法上強制任何同步,io

  • 必須在對象序列化上強制這種同步
  • 線程安全性考慮
  • 注意鎖的使用,規避資源排列死鎖的危險
  • 聲明顯式的序列化UID
    • 這樣避免序列化版本成爲潛在不兼容根源
    • 並且若是沒有顯式UID,會高成本產生一個序列化UID
    • 若是但願新版本可以接受現有序列化實例,就必須使用以前生成的舊版本UID
      • 想要與現有版本不兼容,修改序UID便可
      • 前版本實例反序列化會引起 InvalidClassException異常
相關文章
相關標籤/搜索