帶着問題來學習.
1.序列化是什麼,有什麼作用?
2.序列化有什麼方式?
3.java的序列化以及應用場景是什麼?
4.serialVersionUID 的作用是什麼?
1.序列化是什麼,有什麼作用?
先看看美團一篇文章中的描述,原文點這裏.
互聯網的產生帶來了機器間通訊的需求,而互聯通訊的雙方需要採用約定的協議,序列化和反序列化屬於通訊協議的一部分。通訊協議往往採用分層模型,不同模型每層的功能定義以及顆粒度不同,例如:TCP/IP協議是一個四層協議,而OSI模型卻是七層協議模型。在OSI七層協議模型中展現層(Presentation
Layer)的主要功能是把應用層的對象轉換成一段連續的二進制串,或者反過來,把二進制串轉換成應用層的對象--這兩個功能就是序列化和反序列化。一般而言,TCP/IP協議的應用層對應與OSI七層協議模型的應用層,展示層和會話層,所以序列化協議屬於TCP/IP協議應用層的一部分。本文對序列化協議的講解主要基於OSI七層協議模型。
- 序列化: 將數據結構或對象轉換成二進制串的過程
- 反序列化:將在序列化過程中所生成的二進制串轉換成數據結構或者對象的過程
簡單的理解,A,B雙方需要傳遞一些數據,只能以二進制方式傳輸,然後就A就通過序列化把對象變成二進制串,B接收到二進制串再反序列化成對象.
序列化,反序列化可以說是這些轉換的規則,
傳輸數據就是序列化的作用.大部分講java序列化的應用,都會講把對象存到硬盤之類的,這也是傳輸數據的一種.
2.序列化有什麼方式?
序列化的方式,其實就是序列化的協議.有很多種,xml,json,Thrift,Protobuf,Spearal等等
但是最常見的是xml和json. 這2中形式都有很好的可讀性.
xml由於比較笨重(空間開銷大),貌似現在互聯網用的較少,傳統行業還是多點(web service).
至於各種方式的優劣點,可以參考這裏 (老外測試的,多種序列化協議各方面對比).
3.java的序列化以及應用場景是什麼?
java的序列化是通過實現Serializable接口來實現的.當一個類實現這個接口後,就會被標記爲可序列化.
實現Serializable後,序列化是用默認的方式實現的,如果想自己控制(例如過濾字段及加密文本等)可以實現Externalizable接口,自己覆蓋writeExternal和readExternal方法.
如果是簡單的某個字段不需要序列化,例如密碼,則可以指定字段爲transient.
還有一種方法控制序列化,就是在實現Serializable的類裏面,添加writeObject()和readObject()方法.如下:
private void writeObject(ObjectOutputStream stream) throws ClassNotFoundException, IOException{}
private void readObject(ObjectInputStream stream) throws ClassNotFoundException, IOException{}
就算是private的,在序列化的時候也會被調用,神奇.(可參看think in java 18.12.2);
下面再說說序列化的應用場景:
1).一些配置信息持久化到文件
2).遠程方法調用.
3).保存對象到redis(之類)中.
可能還有別的場景吧. 我就用到了保存到redis這個,jeids的api中,保存參數是byte[],把對象轉換成byte[],就需要用到序列化.
4.serialVersionUID 的作用是什麼?
在eclipse中,當一個類實現Serializable接口後,都會有個警告,大意就是需要一個serialVersionUID.
從字面意思就不難看出,這個字段是序列化的版本.
序列化的時候,會把這個字段一起處理, 當反序列化的時候,會拿當前類的這個字段去和反序列化出來的這個字段做對比.
如果一致,則正常處理.
如果不一致,則拋出異常InvalidClassException.
如果不寫這個字段,則序列化時會自動計算一個值來作爲版本號,當類的屬性變更後,新計算出來的版本值就會和以前不同,這時候反序列化以前的就會報錯.