Java 序列化

摘要: 序列化: 將對象變爲可傳輸內容的過程就是序列化.方式: 1、Java原生: 簡介 Java原生序列化實體類必須實現Serializable接口。 原理是通過Java原生流(InputStream和OutputStream)的方式進行轉化。

序列化:

將對象變爲可傳輸內容的過程就是序列化.
方式:

1、Java原生:

簡介

Java原生序列化實體類必須實現Serializable接口。
原理是通過Java原生流(InputStream和OutputStream)的方式進行轉化。
java原生序列化存在的問題
...

1) 序列化數據結果比較大、傳輸效率比較低;

2) 不能跨語言對接.

以至於在後來的很長一段時間,基於XML格式編碼的對象序列化機制成爲了主流,一方面解決了多語言兼容問題,
另一方面比二進制的序列化方式更容易理解。

再到後來,基於JSON的簡單文本格式編碼的HTTP REST接口又基本上取代了複雜的Web Service接口,
成爲分佈式架構中遠程通信的首要選擇。但是JSON序列化存儲佔用的空間大、性能低。

恰當的序列化協議不僅可以提高系統的通用性、強壯型、安全性、優化性能。同時還能讓系統更加易於調試和擴展

2、Json序列化

Json序列化一般會使用jackson包,通過ObjectMapper類來進行一些操作,比如將對象轉化爲byte數組或者將json串轉化爲對象。
現在的大多數公司都將json作爲服務器端返回的數據格式。比如調用一個服務器接口,通常的請求爲xxx.json?a=xxx&b=xxx的形式。
3、FastJson序列化

fastjson 是由阿里巴巴開發的一個性能很好的Java 語言實現的 Json解析器和生成器。
特點:速度快,測試表明fastjson具有極快的性能,超越任其他的java json parser。
功能強大,完全支持java bean、集合、Map、日期、Enum,支持範型和自省。無依賴,能夠直接運行在Java SE 5.0以上版本, 支持Android。
使用時候需引入FastJson第三方jar包。
4、ProtoBuff序列化

ProtocolBuffer是一種輕便高效的結構化數據存儲格式,可以用於結構化數據序列化。
適合做數據存儲或 RPC 數據交換格式。可用於通訊協議、數據存儲等領域的語言無關、平臺無關、可擴展的序列化結構數據格式。
優點:跨語言;序列化後數據佔用空間比JSON小,JSON有一定的格式,在數據量上還有可以壓縮的空間。
缺點:它以二進制的方式存儲,無法直接讀取編輯,除非你有 .proto 定義,否則無法直接讀出 Protobuffer的任何內容。
其與thrift的對比:兩者語法類似,都支持版本向後兼容和向前兼容,thrift側重點是構建跨語言的可伸縮的服務,支持的語言多,同時提供了全套RPC解決方案,
可以很方便的直接構建服務,不需要做太多其他的工作。 Protobuffer主要是一種序列化機制,在數據序列化上進行性能比較,Protobuffer相對較好。
serialVersionUID的作用

  • 不實現Serializable接口的類不能被序列化, 會拋出NotSerializableException異常

  • 實現Serializable接口, 但沒有定義serialVersionUID值, 反序列化可能會出現local class incompatible異常

    這是基於Java的安全機制. 當序列化對象時, 如果該對象所屬類沒有serialVersionUID, Java編譯器會對jvm中該類的Class文件進行摘要算法生成一個
    serialVersionUID(version1). 保存在序列化結果中. 當反序列化時, jvm會再次對jvm中Class文件摘要生成一個serialVersionUID(version2). 當且僅當被序列化對象的version1=version2時,
    纔會將反序列化結果加載入jvm中, 否則視爲不安全, 拋出local class incompatible異常.
    這樣存在的問題就是, 當對象被序列化後, 其所屬類只要進行過任何改動,會導致摘要算法算出的serialVersionUID變化.
    從而version1 != version2導致拋出異常.
    例如序列化對象存儲在磁盤中後, jvm停止, 並且對其所屬類進行修改. 再次啓動jvm, 當對該對象序列化時就會拋異常.
    不參與序列化

靜態變量不參與序列化 (序列化不保存靜態變量的狀態)

被Transient修飾的成員變量不參與序列化

父子類中, 如果父類沒有序列化, 子類序列化時, 父類的成員不會參與序列化

這種情況多出現在繼承關係, 將common的一些屬性定義在父類, 當父類沒有實現Serializable接口的情況下, 序列化子類時, 父類成員屬性不會參與到序列化中去.
有員工做抽象時, 將公共屬性放在父類, 但父類沒有實現Serializable接口, 導致了自雷序列化時丟失屬性, 進而項目報錯, 找半天錯才發現.

存儲規則

同一對象多次寫入同一文件時, 只會保存一個序列化後的對象a以及多個對a的引用

當同一個文件, 例如b. 當一個對象c多次在b文件中寫入時, 不會保存多個序列化後的對象, 只會保存第一個被序列化後的對象d. 再次存儲c時, 存儲內容爲d的引用.
如果再次存儲時成員屬性發生變化, 例如age值由1變爲2, 那麼本次存儲會增加d的引用以及成員變化值.請添加鏈接描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章