1.3分布式-分布式通訊(序列化)
在網絡中,傳輸數據量較大的內容時,需要使用序列化的方式將對象轉換為字節流的形式在網絡中進行傳輸。這裏簡單的介紹下序列化的幾種方式和基本的知識點。
java序列化機制Serialize接口
java本身的序列化機制存在的問題
1. 序列化數據結果比較大、傳輸效率比較低
2. 不能跨語言對接
以至於在後來的很長一段時間,基於XML格式編碼的對象序列化機制成為了主流,一方面解決了多語言兼容問題,另一方面比二進制的序列化方式更容易理解。以至於基於XML的SOAP協議及對應的WebService框架在很長一段時間內成為各個主流開發語言的必備的技術。
再到後來,基於JSON的簡單文本格式編碼的HTTP REST接口又基本上取代了復雜的Web Service接口,成為分布式架構中遠程通信的首要選擇。但是JSON序列化存儲占用的空間大、性能低等問題,同時移動客戶端應用需要更高效的傳輸數據來提升用戶體驗。在這種情況下與語言無關並且搞笑的二進制編碼協議就成為了大家追求的熱點技術之一。首先誕生的一個開源的二進制序列化框架-MessagePack。它比google的Protocol Buffers出現得還要早
恰當的序列化協議不僅可以提高系統的通用性、強壯型、安全性、優化性能。同時還能讓系統更加易於調試和擴展
序列化和反序列化的概念
把對象轉化為字節序列的過程稱之為對象的序列化
反之,稱之為反序列化
怎麽去實現一個序列化操作
1. 實現Serializable接口
2. ObjectInputStream : 表示讀取指定的字節數據轉換成對象
科普小知識
serialVersionUID的作用
文件流中的class和classpath中的class,也就是修改過後的class,不兼容了,處於安全機制考慮,程序拋出了錯誤,並且拒絕載入。從錯誤結果來看,如果沒有為指定的class配置serialVersionUID,那麽java編譯器會自動給這個class進行一個摘要算法,類似於指紋算法,只要這個文件有任何改動,得到的UID就會截然不同的,可以保證在這麽多類中,這個編號是唯一的。所以,由於沒有顯指定 serialVersionUID,編譯器又為我們生成了一個UID,當然和前面保存在文件中的那個不會一樣了,於是就出現了2個序列化版本號不一致的錯誤。因此,只要我們自己指定了serialVersionUID,就可以在序列化後,去添加一個字段,或者方法,而不會影響到後期的還原,還原後的對象照樣可以使用,而且還多了方法或者屬性可以用。
靜態變量的序列化
序列化並不保存靜態變量的狀態
Transient關鍵字
transient關鍵字表示指定屬性不參與序列化
父子類問題
如果父類沒有實現序列化,而子類實現列序列化。那麽父類中的成員沒辦法做序列化操作
序列化的存儲規則
對同一個對象進行多次寫入,打印出的第一次存儲結果和第二次存儲結果,只多了5個字節的引用關系。
並不會導致文件累加
序列化實現深度克隆
淺拷貝(淺復制、淺克隆):被復制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。
換言之,淺拷貝僅僅復制所拷貝的對象,而不復制它所引用的對象。
深拷貝(深復制、深克隆):被復制對象的所有變量都含有與原來的對象相同的值,除去那些引用其他對象的變量。
那些引用其他對象的變量將指向被復制過的新對象,而不再是原有的那些被引用的對象。
換言之,深拷貝把要復制的對象所引用的對象都復制了一遍
總結
1. 在java中,只要一個類實現了java.io.Serializable接口,那麽它就可以被序列化
2. 通過ObjectOutputStream和ObjectInputStream對對象進行序列化合反序列化操作
3. 對象是否允許被反序列化,不僅僅是取決於對象的代碼是否一致,同時還有一個重要的因素(UID)
4. 序列化不保存靜態變量
5. 要想父類對象也參與序列化操作,那麽必須要讓父類也實現Serializable接口
6. Transient關鍵字,主要是控制變量是否能夠被序列化。如果沒有被序列化的成員變量反序列化後,會被設置成初始值,比如String -> null
7. 通過序列化操作實現深度克隆
主流的序列化技術有哪些
JSON/Hessian(2) /xml/protobuf/kryo/MsgPack/FST/thrift/protostuff/Avro
1.3分布式-分布式通訊(序列化)