Java之序列化和反序列化

在Java中,除了面向對象三大特性(封裝、繼承、多態,<抽象類>)以外,還有一個概念就是序列化和反序列化,那麼很多人肯定會有疑問:

(1):什麼是序列化和反序列化?

(2):什麼情況下需要序列化?

(3):實現序列化接口之後爲什麼會有個serialVersionUID 

一:什麼是序列化,什麼是反序列化?

序列化:把對象轉換爲字節序列的過程稱爲對象的序列化。

反序列化:把字節序列恢復爲對象的過程稱爲對象的反序列化。

二:什麼情況下需要序列化?

<1>:當你想把的內存中的對象狀態保存到一個文件中或者數據庫中時候;
<2>:當你想用套接字在網絡上傳送對象的時候;
<3>:當你想通過RMI傳輸對象的時候;

三:什麼是serialVersionUID ?

serialVersionUID適用於Java的序列化機制。簡單來說,Java的序列化機制是通過判斷類的serialVersionUID來驗證版本一致性的。在進行反序列化時,JVM會把傳來的字節流中的serialVersionUID與本地相應實體類的serialVersionUID進行比較,如果相同就認爲是一致的,可以進行反序列化,否則就會出現序列化版本不一致的異常,即是InvalidCastException

實際案例:序列化以及反序列化:

《1》聲明一個實體類:

package com.sf.code.serial;

import java.io.Serializable;

public class Person implements Serializable {
    private static final long serialVersionUID = 1234567890L;
    public int id;
    //public String name;
    
    public int age;

    public Person(int id, String name) {
        this.id = id;
        //this.name = name;
    }

    public String toString() {
        return "Person: " + id 
                //+ ",name:" + name 
                + ",age:" + age;
    }
}


public class SerialTest {

    public static void main(String[] args) throws IOException {
        //序列化
        Person person = new Person(1234, "wang", 100);
        System.out.println("Person Serial" + person);
        FileOutputStream fos = new FileOutputStream("D://Person.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(person);
        oos.flush();
        oos.close();
       
        // 反序列化
        Person person;
        FileInputStream fis = new FileInputStream("D://Person.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        person = (Person) ois.readObject();
        ois.close();
        System.out.println("Person Deserial" + person);
        
    }

}


控制檯輸出:Person DeserialPerson: 1234,name:wang

如果修改了serialVersionUID 反序列化就會失敗報錯

下面是摘自 jdk api 文檔裏面關於接口 Serializable 的描

類通過實現 java.io.Serializable 接口以啓用其序列化功能。
未實現此接口的類將無法使其任何狀態序列化或反序列化。
可序列化類的所有子類型本身都是可序列化的。因爲實現接口也是間接的等同於繼承。
序列化接口沒有方法或字段,僅用於標識可序列化的語義。

關於 serialVersionUID 的描述
序列化運行時使用一個稱爲 serialVersionUID 的版本號與每個可序列化類相關聯,該序列號在反序列化過程中用於驗證序列化對象的發送者和接收者是否爲該對象加載了與序列化兼容的類。如果接收者加載的該對象的類的 serialVersionUID 與對應的發送者的類的版本號不同,則反序列化將會導致 InvalidClassException。可序列化類可以通過聲明名爲 "serialVersionUID" 的字段(該字段必須是靜態 (static)、最終 (final) 的 long 型字段)顯式聲明其自己的 serialVersionUID:

如果可序列化類未顯式聲明 serialVersionUID,則序列化運行時將基於該類的各個方面計算該類的默認 serialVersionUID 值,如“Java(TM) 對象序列化規範”中所述。不過,強烈建議 所有可序列化類都顯式聲明 serialVersionUID 值,原因是計算默認的 serialVersionUID 對類的詳細信息具有較高的敏感性,根據編譯器實現的不同可能千差萬別,這樣在反序列化過程中可能會導致意外的 InvalidClassException。因此,爲保證 serialVersionUID 值跨不同 java 編譯器實現的一致性,序列化類必須聲明一個明確的 serialVersionUID 值。還強烈建議使用 private 修飾符顯示聲明 serialVersionUID(如果可能),原因是這種聲明僅應用於直接聲明類 -- serialVersionUID 字段作爲繼承成員沒有用處。數組類不能聲明一個明確的 serialVersionUID,因此它們總是具有默認的計算值,但是數組類沒有匹配 serialVersionUID 值的要求。

文章結尾很多人肯定會說,爲什麼沒有提到 爲什麼要用序列化?

其實,在之前,可能,我們的傳輸方式,一般都是通過對象的形式進行傳輸,進而引出了序列化的概念,其實,現在我們現在普遍都是用JSON進行傳出了、所以,有些時候 也無須實現、當然,現在也有JSON的序列化和反序列化

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章