概念
序列化:把對象轉化為可傳輸的字節序列過程稱為序列化。
反序列化:把字節序列還原為對象的過程稱為反序列化。
為什么需要序列化
序列化最終的目的是為了對象可以跨平台存儲,和進行網絡傳輸。而我們進行跨平台存儲和網絡傳輸的方式就是IO,而我們的IO支持的數據格式就是字節數組。
因為我們單方面的只把對象轉成字節數組還不行,因為沒有規則的字節數組我們是沒辦法把對象的本來面目還原回來的,所以我們必須在把對象轉成字節數組的時候就制定一種規則(序列化),那么我們從IO流里面讀出數據的時候再以這種規則把對象還原回來(反序列化)。
如果我們要把一棟房子從一個地方運輸到另一個地方去,序列化就是我把房子拆成一個個的磚塊放到車子里,然后留下一張房子原來結構的圖紙,反序列化就是我們把房子運輸到了目的地以后,根據圖紙把一塊塊磚頭還原成房子原來面目的過程
什么情況下需要序列化
通過上面我想你已經知道了凡是需要進行“跨平台存儲”和”網絡傳輸”的數據,都需要進行序列化。
本質上存儲和網絡傳輸 都需要經過 把一個對象狀態保存成一種跨平台識別的字節格式,然后其他的平台才可以通過字節信息解析還原對象信息。
序列化的方式
序列化只是一種拆裝組裝對象的規則,那么這種規則肯定也可能有多種多樣,比如現在常見的序列化方式有:
JDK(不支持跨語言)、JSON、XML、Hessian、Kryo(不支持跨語言)、Thrift、Protostuff、FST(不支持跨語言)
Java 序列化
java 實現序列化很簡單,只需要實現Serializable 接口即可。
public class User implements Serializable{ //年齡 private int age; //名字 private String name ; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
注意: JAVA序列化中常見的問題
- 問題一:static 屬性不能被序列化
原因:序列化保存的是對象的狀態,靜態變量屬於類的狀態,因此 序列化並不保存靜態變量。
- 問題二:Transient 屬性不會被序列化
- 問題三:序列化版本號serialVersionUID
所有實現序列化的對象都必須要有個版本號,這個版本號可以由我們自己定義,當我們沒定義的時候JDK工具會按照我們對象的屬性生成一個對應的版本號。使用JDK生成的serialVersionUID,只要對象有一丁點改變serialVersionUID就會隨着變更。因此建議自己手動定義該版本號。
Redis 序列化
當你用Redis的key和value時,value對於redis來講就是個byte array。你要自己負責把你的數據結構轉換成byte array,等讀取時再讀出來。
一個特例是字符串,因為字符串自己幾乎就已經是byte array了,所以不需要自己處理。
233
參考文章
https://zhuanlan.zhihu.com/p/40462507
https://www.zhihu.com/question/277363840/answer/392945240