JAVA序列化為什么要使用SerialversionUID

1.首先談談什么是字節,先扯會,哈哈?
字節是計算機中傳輸的最小單位,一個字節等于8位。一個0和1就是一位,兩位就是一個字。
2.談談為什么要序列化對象?
把對象轉換為字節序列的過程稱為對象的序列化。
  把字節序列恢復為對象的過程稱為對象的反序列化。
  對象的序列化主要有兩種用途:
  1) 把對象的字節序列永久地保存到硬盤上,通常存放在一個文件中;
  2) 在網絡上傳送對象的字節序列。

在很多應用中,需要對某些對象進行序列化,讓它們離開內存空間,入住物理硬盤,以便長期保存。比如最常見的是Web服務器中的Session對象,當有 10萬用戶并發訪問,就有可能出現10萬個Session對象,內存可能吃不消,于是Web容器就會把一些seesion先序列化到硬盤中,等要用了,再把保存在硬盤中的對象還原到內存中。

當兩個進程在進行遠程通信時,彼此可以發送各種類型的數據。無論是何種類型的數據,都會以二進制序列的形式在網絡上傳送。發送方需要把這個Java對象轉換為字節序列,才能在網絡上傳送;接收方則需要把字節序列再恢復為Java對象
3.為什么要使用SerialversionUID呢
簡單看一下 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.
如果用戶沒有自己聲明一個serialVersionUID,接口會默認生成一個serialVersionUID
However, it is stronglyrecommended that all serializable classes explicitly declareserialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpectedInvalidClassExceptions during deserialization.
但是強烈建議用戶自定義一個serialVersionUID,因為默認的serialVersinUID對于class的細節非常敏感,反序列化時可能會導致InvalidClassException這個異常。
e.g:1.使用默認的serialVersionUID
我們先建一個實體類Person 實現Serializable接口
public class Person implements Serializable {

private int age;
private String name;
private String sex;


public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

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 class TestPersonSerialize {

public static void main(String[] args) throws Exception {
    serializePerson();
    Person p = deserializePerson();
    System.out.println(p.getName()+";"+p.getAge());


}

private static void serializePerson() throws FileNotFoundException,IOException {
    Person person = new Person();
    person.setName("測試實例");
    person.setAge(25);
    person.setSex("male");

    ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
            new File("E:/person.txt")));
    oo.writeObject(person);
    System.out.println("序列化成功");
    oo.close();
}

private static Person deserializePerson() throws IOException, Exception {
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:/person.txt")));
    Person person = (Person) ois.readObject();
    System.out.println("反序列化成功");
    return person;
}

}


image.png

如果我們先盡心序列化,然后在反序列化之前修改了Person類會怎樣呢

public class Person implements Serializable {

private int age;
private String name;
private String sex;
private String address;

public String getAddress() {
    return address;
}

public void setAddress(String address) {
    this.address = address;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

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;
}

}


image.png

可以看到,當我們修改Person類的時候,Person類對應的SerialversionUID也變化了,而序列化和反序列化就是通過對比其SerialversionUID來進行的,一旦SerialversionUID不匹配,反序列化就無法成功。在實際的生產環境中,我們可能會建一系列的中間Object來反序列化我們的pojo,為了解決這個問題,我們就需要在實體類中自定義SerialversionUID。
  e.g:3 在Person類中加入自定義SerialversionUID

序列化的方法:使用輸入輸出流。

transient 不許序列化,可以加載某個字段上。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。