java序列化和反序列化中的serialVersionUID有啥用


 1.什么是序列化和反序列化

  序列化就是將java對象轉成字節序列的過程;反序列化就是將字節序列轉成java對象的過程。

   java中,序列化的目的一種是需要將對象保存到硬盤上,一種是對象需要在網絡中傳輸

2.序列化和反序列化的方式

  序列化和反序列化有很多種方式,如JDK類庫中提供的序列化API、常用的json工具類等。本篇博客使用JDK提供的序列化API進行演示。重點說明serialVersionUID的作用。

  假設現在有一個Student類,我們要對Student類進行序列化操作

  ①該類必須實現Serializable接口

public class Student implements Serializable{

    private static final long serialVersionUID = -595470438262181967L;

    private String name ;
     
    private String sex;
    
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
    
}

  ②在main方法中執行序列化和反序列化操作

    public static void main(String[] args) throws Exception {
        
        //序列化
        OutputStream os = new FileOutputStream(new File("D://student.txt"));
        ObjectOutputStream oos = new ObjectOutputStream(os);
        Student student = new Student();
        student.setName("張三");
        student.setSex("男");
        oos.writeObject(student);
        
        //反序列化
        InputStream is = new FileInputStream(new File("D://student.txt"));
        ObjectInputStream ois = new ObjectInputStream(is);
        Student student1 = new Student();
        student1 = (Student) ois.readObject();
        System.out.println(student1.getName());
    }

  輸出結果:張三

  即student1對象在反序列化時進行了賦值

3.為什么要serialVersionUID

  s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D​:​ ​字​面​意​思​上​是​序​列​化​的​版​本​號​,凡是實現Serializable接口的類都有一個表示序列化版本標識符的靜態變量。

  (1)下面進行測試,如果沒有s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D會出現什么?

    ①去掉Student類中的s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D屬性。執行main方法,結果顯示序列化成功!輸出張三

    ②修改Student類,在Student類中添加number字段

public class Student implements Serializable{

    private String name ;
     
    private String sex;

    private String number;
    
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }
    
}

  不執行序列化方法,只執行反序列化方法,結果出現異常:

Exception in thread "main" java.io.InvalidClassException: com.iot.study.serialize.Student; local class incompatible: stream classdesc serialVersionUID = -595470438262181967, local class serialVersionUID = -4254220179260112271
    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:621)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
    at com.iot.study.serialize.Client.main(Client.java:35)

  意思是原來序列化的時候(沒有指定serialVersionUID)硬盤存的class的 serialVersionUID = -595470438262181967,而當前class的serialVersionUID = -4254220179260112271。 二者不一樣,無法反序列化。

  原因分析:

    serialVersionUID沒有指定時,java編譯器會自動給這個class進行一個摘要算法,類似於指紋算法,只要這個文件 多一個空格,得到的UID就會截然不同的,可以保證在這么多類中,這個編號是唯一的。所以,添加了一個number字段后,由於沒有顯指定 serialVersionUID,編譯器又為我們生成了一個UID,當然和前面保存在文件中的那個不會一樣了,於是就出現了2個序列化版本號不一致的錯誤。

  (2)指定serialVersionUID測試

  如果為Student類顯示的指定serialVersionUID,那么在序列化和反序列化的時候,即使修改了Student類中的部分內容,也能序列化成功。

4.serialVersionUID的取值

  serialVersionUID的取值是Java運行時環境根據類的內部細節自動生成的。如果對類的源代碼作了修改,再重新編譯,新生成的類文件的serialVersionUID的取值有可能也會發生變化。
  類的serialVersionUID的默認值完全依賴於Java編譯器的實現,對於同一個類,用不同的Java編譯器編譯,有可能會導致不同的 serialVersionUID,也有可能相同。為了提高serialVersionUID的獨立性和確定性,強烈建議在一個可序列化類中顯示的定義serialVersionUID,為它賦予明確的值

  顯式地定義serialVersionUID有兩種用途:
    1、 在某些場合,希望類的不同版本對序列化兼容,因此需要確保類的不同版本具有相同的serialVersionUID;
    2、 在某些場合,不希望類的不同版本對序列化兼容,因此需要確保類的不同版本具有不同的serialVersionUID。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM