回覆列表
  • 1 # 肥貓技術生活

    序列化是物件實現持久化的一個過程,基本主流的開發語言都有序列化的概念,與之相反的概念是反序列化。

    對比理解:

    1、把java物件比喻為,透過樂高積木按照圖紙搭建的一座大廈,如果要把這座大廈透過火車運到另一個地方,這時候就需要按照操作規範(介面規範)把高樓拆卸成積木塊(序列化的過程),運輸到目的地後,再按照圖紙重新搭建出一模一樣的大廈(反序列化)。

    2、javascript中常用JSON.parse()和JSON.stringify(),就是一組常用的序列號和反序列化的概念。

    序列化:

    Java中實現Serializable介面,一般可以實現物件的序列化。目的可能有

    1、持久化儲存,如儲存在檔案或資料庫等。

    2、以流的形式在網路中進行傳遞和接收,方便溝通交流。

    與之對應的是反序列化,即把流轉換為物件,就可以正常的使用物件了。

    總結:

    java序列化主要是為了不同事物(程式設計物件、OS之間、網路之間等)之間進行儲存、運輸、溝通、交流等目的。

    個人愚見,僅供參考!

  • 2 # 程式猿W

    下面我將從以下幾點來介紹:

    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 都可以

    ④ Avro 設計理念偏於動態型別語言,那麼這類的場景使用 Avro 是可以的

  • 3 # 深圳小小楓

    我想先談談序列化和反序列化,深入淺出吧。

    網路傳輸和持久化(簡單地理解為儲存起來)都是有開銷的,開銷越小,效能越高。那作為物件,能夠透過轉換格式來處理,甚至理解為壓縮也行,那就大大降低開銷了。所以就有了序列化。

    有序列化,就有反序列化,這是成對出現的。畢竟轉換了格式就得轉換回來,就像加密和解密一樣。

    那麼聊回Java,Java處理序列化就是實現Serializable介面。如果你判斷該物件需要透過網路傳輸、儲存,那麼就果斷實現介面吧。

    噢~k。搞定!回答完畢。

  • 4 # avatasia

    java物件常量在棧 其他在堆 如果要傳輸 肯定是連續的位元流 一般的序列化特指位元流序列化 實現serializable介面 虛擬機器會自動使用內建的序列化方法 當然也可以用其他的序列化框架

    json序列化 xml序列化是另外一回事

  • 5 # 小創程式設計

    要知道實現這個介面的原因,首先得需要了解這個介面的目的!

    Serializable 介面的作用

    我們先來看一下,Java API 文件對這個介面的解釋:

    實現了 java.io.Serializable 介面的類就表示是可序列化的,未實現此介面的類將不會將其任何狀態序列化或反序列化。此介面沒有方法或欄位,僅用於標識可序列化的語義。

    所以,這個問題就變成了,Java 物件為什麼要序列化?我覺得有以下兩個原因:

    - 物件持久化:典型的比如 HTTP Session 物件,預設在記憶體中,重啟後就會話就沒了,為了保持會話,可以把它序列化到檔案或者資料庫

    - 分散式物件:比如 RMI(Remote Method Invocation, 雖然已經用的不多了),呼叫遠端主機上的服務時,可以直接使用物件作為引數,方法就像在本地使用一樣

    序列化和反序列化的內容是什麼

    序列化,就是透過 ObjectOutputStream 將物件的一部分欄位值,甚至是集合欄位的內容寫入到一個檔案中。

    反序列化,就是使用 ObjectInputStream 按照之前寫入的方式,從二進位制檔案中,讀取內容,生成一個對應類的例項物件。

  • 6 # 夕陽雨晴

    Serializable是java.io包中定義的、用於實現Java類的序列化操作而提供的一個語義級別的介面。Serializable序列化介面沒有任何方法或者欄位,只是用於標識可序列化的語義。實現了Serializable介面的類可以被ObjectOutputStream轉換為位元組流,同時也可以透過ObjectInputStream再將其解析為物件。

    序列化:序列化就是把物件的狀態資訊轉化為可儲存或傳輸的形式過程,也就是把物件轉化為位元組序列的過程稱為物件的序列化。反序列化:序列化的逆向過程,把位元組陣列反序列化為物件,把位元組序列恢復為物件的過程成為物件的反序列化。

    物件序列化的兩種用途:

    物件序列化的兩種用途:1.物件持久化,把物件的位元組序列永久地儲存到硬碟上,通常存放在一個檔案中;2.網路傳輸物件,在網路上傳送物件的位元組序列。可以透過序列化把主機A程序上的物件序列化為二進位制序列,傳輸到主機B上的程序從序列中重構出該物件。

    serialVersionUID的作用。對於JVM來說,要進行持久化的類必須要有一個標記,只有持有這個標記JVM才允許類建立的物件可以透過其IO系統轉換為位元組資料,從而實現持久化,而這個標記就是Serializable介面。而在反序列化的過程中則需要使用serialVersionUID來確定由那個類來載入這個物件,所以我們在實現Serializable介面的時候,一般還會要去儘量顯示地定義serialVersionUID,如:

    private static final long serialVersionUID = 1L;

    在反序列化的過程中,如果接收方為物件載入了一個類,如果該物件的serialVersionUID與對應持久化時的類不同,那麼反序列化的過程中將會導致InvalidClassException異常。例如,在之前反序列化的例子中,我們故意將User類的serialVersionUID改為2L,如:

    private static final long serialVersionUID = 2L;

    那麼此時,在反序例化時就會導致異常,如下:

    java.io.InvalidClassException: cn.wudimanong.serializable.User; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2

    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:687)

    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1880)

    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1746)

    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2037)

    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1568)

    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:428)

    at cn.wudimanong.serializable.SerializableTest.readObj(SerializableTest.java:31)

    at cn.wudimanong.serializable.SerializableTest.main(SerializableTest.java:44)

    序列化的注意事項:1.序列化時,只對物件的狀態進行儲存,而不管物件的方法;2.當一個父類實現序列化,子類自動實現序列化,不需要顯式實現Serializable介面;3.當一個物件的例項變數引用其他物件,序列化該物件時也把引用物件進行序列化;4.序列化會忽略靜態變數,即序列化不儲存靜態變數的狀態,靜態成員屬於類級別的,不能序列化,添加了static、transient關鍵字後的變數不能序列化;5.在序列化物件時,不僅會序列化當前物件本身,還會對該物件引用的其它物件也進行序列化,如此引用傳遞序列化;6.如果一個物件包含的成員變數是容器類等並深層引用,那麼序列化過程開銷也較大。

    最後提一下,常見的序列化技術:1.java 序列化;2.XML序列化;3.JSON序列化;4.Hessian 序列化;5.Protobuf 序列化。

  • 7 # 大象聊科技

    在Java世界中,是面向物件的程式設計,但計算機處理物件的時候,不可能只在一個機器上進行處理,有可能需要其它機器提供計算能力,這個時候,就需要將物件從某一臺機器,複製到其它機器上去。這個時候Serializable就非常的有作用,任何實現了Serializable介面的物件,均可以在一臺機器上將物件序列化為二進位制欄位,然後在其它機器上透過反序列化,將物件還原出來。這樣就實現了乾坤大轉移。

    因為Java世界中很少存在只有單點執行的工作例項,所以需要Java物件實現序列化介面:Serializable。

  • 中秋節和大豐收的關聯?
  • 學技術,學java好還是C++好,兩個之間有何區別啊?