序列化是經過某種算法將存儲於內存中的對象轉換成能夠用於持久化存儲或者通訊的形式的過程前端
反序列化是將這種被持久化存儲或者通訊的數據經過對應解析算法還原成對象的過程,它是序列化的逆向操做算法
前端請求後端接口數據的時候,後端須要返回 JSON 數據,這就是後端將 Java 堆中的對象序列化爲了 JSON 數據傳給前端,前端能夠根據自身需求直接使用或者將其反序列化爲 JS 對象後端
RPC 遠程調用過程當中,調用者和被調用者必須約定好序列化和反序列化算法,好比 A 應用將 User 對象序列化爲了 JSON 數據傳給 B 應用,User 對象數據爲 {"id": 1, "name": "long"}
,到達 B 應用的時候須要將這些數據反序列化爲對象,若是此時 B 應用的反序列化算法是 XML 的話那麼確定就解析失敗了,因此必須都得約定好他們都採用 JSON 序列化算法,那麼基於 JSON 標準就能成功解析出 User 對象數組
若是某個字段咱們不想經過 Java 默認序列化機制輸出,咱們就能夠經過該字段來代表當前字段不須要被序列化性能
咱們想經過自定義的方式將 address 數據序列化優化
其中的 writeObject 做用於寫序列化數據的時候會反射調用該方法,readObject 會在反序列化的時候調用3d
若是咱們沒有自定義 serialVersionUID 的話,會根據當前類的信息自動生成,若是當前類沒有作修改那麼生成的 serialVersionUID 是一致的,若是修改後 serialVersionUID 就會改變致使沒法反序列化,因此在平常使用中咱們必定要填寫該字段code
最開始看代碼的時候,不要一下就陷入所有細節,咱們應該只看咱們目前關注的點,當認識逐漸深入以後再來看一些細節,否則的話容易看的一臉懵逼 cdn
首先調用objectOutputStream.writeObject(user);
而後調用 writeObject0(obj, false);
在這個方法裏面有這樣一段代碼對象
首先將 TC_OBJECT 這一個對象標誌位寫入到流中,標識着當前開始寫一個的數據是一個對象,而後調用 writeSerialData 開始寫入具體數據
首先會得到 ClassDataSlot 咱們能夠把它看作是提供了序列化對象的輔助手段
在此經過 ClassDataSlot 去檢查序列化對象中是否實現了 writeObject 這個方法,那麼這個 writeObjectMethod 是在何時初始化的呢?立刻會講到
若是實現了 writeObject 咱們就去反射調用該方法
若是當前類沒有實現 writeObject 方法就調用默認的 defaultWriteFields 去寫數據
在上文咱們知道是經過 writeObjectMethod 這個來判斷的,那麼這個字段是在哪裏初始化的呢,咱們回到 ObjectOutputStream 的 writeObject0 方法,在調用後續的 writeOrderinaryObject 方法以前有這樣一段代碼
而後咱們回到 defaultWriteFields(Object obj, ObjectStreamClass desc) 繼續來看
反序列化其實就是序列化的逆向過程,若是你看懂了序列化的關鍵代碼,那麼看這個過程就不會很難,下面貼出關鍵代碼作出分析
這裏可以看到會根據反序列對象的具體類型分別作不一樣的處理,咱們當前的對象是 User 對象因此會進入箭頭指向的方法
對於 String 類型來講,在反序列化第一張中會調用讀取對應的值
一個新的技術的誕生都是有必定的緣由和背景的,好比說 Java 原生序列化後數據比較大,傳輸效率低,同時又又沒法跨語言通訊,因此不少人選擇使用 XML 的來序列化數據,XML 序列化後卻是解決了跨語言通訊的問題,可是它序列化後的數據比原生數據還要大,因此就誕生了 JSON 序列化,他支持跨語言,而且序列化後的數據遠遠小於前 2 者,最後有人想進一步的優化大小就引入了 Protobuf 它具有 壓縮的功能,被壓縮的數據小於 JSON 序列化後的數據。
其它的序列化方式
後面會寫一篇文章就會來聊聊其它的序列化方式對比下他們的性能和底層使用原理