Java對象為啥要實現Serializable接口?
下面我將從以下幾點來介紹:
1、什么是序列化和反序列化?
2、Java對象為什么要實現Serializable接口?
3、使用Serializable接口需要注意的問題?
4、常見的序列化技術?
5、序列化技術的選型
什么是序列化和反序列化?1、序列化
序列化就是把對象的狀態信息轉化為可存儲或傳輸的形式過程,也就是把對象轉化為字節序列的過程稱為對象的序列化。
2、反序列化
序列化的逆向過程,把字節數組反序列化為對象,把字節序列恢復為對象的過程成為對象的反序列化。
Java對象為什么要實現Serializable接口?對象序列化的兩種用途:
(1) 對象持久化:把對象的字節序列永久地保存到硬盤上,通常存放在一個文件中;
Java 平臺允許我們在內存中創建可復用的Java對象,但一般情況下,只有當JVM處于運行時,這些對象才可能存在,即,這些對象的生命周期不會比JVM的生命周期更長。但是在現實應用中,就可能要求在JVM停止運行之后能夠保存(序列化)指定的對象,并在將來重新讀取被保存的對象。Java對象序列化就能夠幫助我們實現該功能。
(2) 網絡傳輸對象:在網絡上傳送對象的字節序列。可以通過序列化把主機A進程上的對象序列化為二進制序列,傳輸到主機B上的進程從序列中重構出該對象。
還有一種情況是兩個進程之間進行通信時,兩方發送各種類型的數據。無論何種類型的數據,都會以二進制序列的形式在網絡上進行傳送。發送方需要把對象轉換成字節序列,才能在網絡上傳送;接收方 則需要把字節序列再恢復成對象。
在java中只要一個類實現了java.io.Serializable 接口,那么它就可以被序列化。
java實現對對象序列化的方式:
JDK提供了Java對象的序列化方式,主要通過輸出流 java.io.ObjectOutputStream 和 對象輸入流 java.io.ObjectInputStream 來實現。其中,被序列化的對象需要 實現
java.io.Serializable
接口。使用Serializable接口需要注意的問題?1.serialVersionUID的作用
Java的序列化機制是通過判斷類的 serialVersionUID 來驗證版本一致性的。在進行反序列化時,JVM 會把傳來的字節流中的 serialVersionUID與本地相應實體類的 serialVersionUID 進行比較,如果相同就認為是一致的,可以進行反序列化,否則就會出現序列化版本不一致的異常,即是 InvalidCastException。
如果沒有為指定的 class 配置 serialVersionUID,那么 java 編譯器會自動給這個 class 進行一個摘要算法,類似于指紋算法,只要這個文件有任何改動,得到的 UID 就會截然不同的,可以保證在這么多類中,這個編號是唯一的
serialVersionUID有兩種生成方式
(1) 默認的1L,比如:private static final long serialVersionUID = 1L;
(2) 根據類名、接口名、成員方法及屬性等來生成一個64位的哈希字段
當 實 現 java.io.Serializable 接 口 的 類 沒 有 顯 式 地 定 義 一 個serialVersionUID 變量時候,Java 序列化機制會根據編譯的 Class 自動生成一個 serialVersionUID 作序列化版本比較用,這種情況下,如果Class 文件(類名,方法明等)沒有發生變化(增加空格,換行,增加注釋等等),就算再編譯多次,serialVersionUID 也不會變化的。
2、靜態變量序列化
序列化時并不保存靜態變量,這其實比較容易理解,序列化保存的是對象的狀態,靜態變量屬于類的狀態,因此 序列化并不保存靜態變量。
3、Transient關鍵字
作用是控制變量的序列化,在變量聲明前加上該關鍵字,可以阻止該變量被序列化到文件中,在被反序列化后,transient變量的值設為初始值,如int型的是0.
4.、序列化的存儲規則
(1) 同一個對象兩次(開始寫入文件到最終關閉流的這個過程算一次),如果不關閉流寫入文件兩次,則第二次寫入對象時文件只增加5字節。
(2) Java序列化機制為了節省磁盤空間,具有特定的存儲規則,當寫入文件為同一對象時,并不會再將對象的內容進行存儲,而只是再次存儲一份引用,上面增加的5字節的存儲空間就是新增 引用和一些控制信息的空間。反序列化時,恢復引用關系,該存儲規則極大的節省了存儲空間。
5、序列化實現深克隆
在java中存在一個Cloneable接口,通過實現這個接口的類都會具備clone的能力,同時clone在內存中進行,在性能方面會比我們直接通過new生成對象要高一些,特別是一些大的對象的生成,性能提升相對比較明顯。
常見的序列化技術1、java 序列化
優點:java語言本省提供,使用比較方面和簡單
缺點:不支持跨語言處理、想能相對不是很好,序列化以后產生的數據相對較大
2、XML序列化
XML序列化的好處在于可讀性好,方面閱讀和調試。但是序列化以后的 字節碼文件比較大,而且效率不高,適應于對性能不高,而且QPS較低的企業級內部系統之間的數據交換的場景,同時XML又具有語言無慣性,所以還可以用于異構系統之間的數據交換和協議。比如我們熟知的WebService,就是采用XML格式對數據進行序列化的
3、JSON序列化
JSON(JavaScript Object Notation)是一種輕量級的數據交換格式,相對于XML來說,JON的字節流較小,而且可讀性也非常好。現在JSON數據格式的其他運用最普遍的。
4、Hessian 序列化框架子
Hessian是一個支持跨語言傳輸的二進制序列化協議,相對于Java默認的序列化機制來說,Hessian具有更好的性能和易用性,而且支持對重不同的語言,實際上Dubbo采用的就是Hessian序列化來實現,只不過Dubbo對Hessian進行重構,性能更高。
5、Protobuf 序列化框架
Protobuf是Google的一種數據交換格式,它獨立于語言、獨立于平臺。
Google 提供了多種語言來實現,比如 Java、C、Go、Python,每一種實現都包含了相應語言的編譯器和庫文件Protobuf 使用比較廣泛,主要是空間開銷小和性能比較好,非常適合用于公司內部對性能要求高的 RPC 調用。 另外由于解析性能比較高,序列化以后數據量相對較少,所以也可以應用在對象的持久化場景中但是但是要使用 Protobuf 會相對來說麻煩些,因為他有自己的語法,有自己的編譯器。
序列化技術的選型1、技術層面
① 序列化空間開銷,也就是序列化產生的結果大小,這個影響到傳輸的性能
② 序列化過程中消耗的時長,序列化消耗時間過長影響到業務的響應時間
③ 序列化協議是否支持跨平臺,跨語言。因為現在的架構更加靈活,如果存在異構系統通信需求,那么這個是必須要考慮的
④ 可擴展性/兼容性,在實際業務開發中,系統往往需要隨著需求的快速迭代來實現快速更新,這就要求我們采用的序化協議基于良好的可擴展性/兼容性,比如在現有的序列化數據結構中新增一個業務字段,不會影響到現有的服務
⑤技術的流行程度,越流行的技術意味著使用的公司多,那么很多坑都已經淌過并且得到了解決,技術解決方案也相對成熟
⑥ 學習難度和易用性
2、選型建議
① 對性能要求不高的場景,可以采用基于 XML 的 SOAP 協議
② 對性能和間接性有比較高要求的場景,那么Hessian、Protobuf、Thrift、Avro 都可以
③ 基于前后端分離,或者獨立的對外的 api 服務,選用 JSON 是比較好的,對于調試、可讀性都很不錯
④ Avro 設計理念偏于動態類型語言,那么這類的場景使用 Avro 是可以的