天天看點

為什麼要使用serialVersionUID

1. 序列化是什麼

  • 把對象轉換為位元組序列的過程稱為對象的序列化 。
  • 把位元組序列恢複為對象的過程稱為對象的反序列化。

2. Java中如何使用序列化

隻需要讓對象實作

Serializable

接口即可,如下:

/**
 * @author lirong
 * @desc 序列化類
 * @date 2019/05/18 12:04
 */
public class Person implements Serializable {

    private static final long serialVersionUID = 1L;

    private int id;
    private String name;

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }
    
    @Override
    public String toString() {
        return "Person: " +
                ", id: "+ id +
                ", name: " + name;
    }
}
           

讓我們來看看

Serializable

接口都幫我們做了什麼工作?

If a serializable class does not explicitly declare a serialVersionUID,
   then the serialization runtime will calculate a default 
   serialVersionUID value for that class based on various aspects of the class, 
  as described in the Java(TM) Object Serialization Specification. 
           

大緻意思就是:如果沒有為Class顯示的聲明

serialVersionUID

的話,運作時JVM将預設為Class根據Class的各個字段屬性生成一個

serialVersionUID

,具體生成方式就不做研究了,大緻應該是根據各字段的hash值湊成的吧。

3. 測試代碼

3.1 序列化測試類:

/**
 * @author lirong
 * @desc 序列化測試類
 * @since 2019/05/18 12:09
 */
public class SerialTest {

    public static void main(String[] args) throws IOException {
        Person person = new Person(1234, "Janche");
        System.out.println("Person Serial" + person);
        FileOutputStream fos = new FileOutputStream("Person.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(person);
        oos.flush();
        oos.close();
    }
}
           

3.2 反序列化測試類

/**
 * @author lirong
 * @desc 反序列化測試類
 * @date 2019/05/18 12:16
 */
public class DeserialTest {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileInputStream fis = new FileInputStream("Person.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Person person = (Person) ois.readObject();
        ois.close();
        System.out.println("Person Deserial" + person);
    }
}

           

4. 測試條件

a. 不實作

Serializable

接口

b. 實作

Serializable

接口

c. 未自定義

serialVersionUID

字段

d. 自定義

serialVersionUID

字段

e. 反序列化前增加字段

f. 反序列化前減少字段

g. 反序列化前修改字段的類型

說明:反序列化前 表示 在序列化操作完成之後到反序列化開始之前這段時間,更改

Person

類的字段
5. 測試結果
1.隻要有a出現,就會導緻

java.io.NotSerializableException

異常,即無法完成序列化。

2.當條件為 b+c 或者 b+d 時,序列化和反序列化均正常執行。

3.當條件為 b+c+e 或者 b+c+f 時,反序列化時将抛出

InvalidClassException

異常。

4.當條件為 b+d+e 或者 b+d+f 時,序列化和反序列一切正常,增加字段時,反序列化出來該字段為預設值,減少字段時,反序列化出來也将沒有此字段。

5.當條件包含 g 時,反序列化也将抛出

InvalidClassException

異常。
6. 測試總結
1. 盡量為每一個需要序列化的類自定義

serialVersionUID

值,這樣可避免因為Class中字段的修改而帶來的反序列化異常。

2. 盡量不要修改序列化類中的字段類型,如果一定要修改,請重新序列化後再反序列化。

3. 如果要為序列化的類中忽略某個字段,可添加

transient

關鍵字

繼續閱讀