Java序列化和反序列化

什麼叫序列化和反序列化?

序列化:對象轉化爲字節序列的過程叫做對象的序列化

反序列化:字節序列恢復爲對象的過程叫做對象的反序列化

 

爲啥要序列化?(序列化的用途)

-需要將對象永久的保存在硬盤中(比如Session對象)

-網絡傳輸對象的序列(網絡中的二進制序列)

 

過程:

序列化的過程:創建一個對象輸出流對象,調用對象的writeObject()函數

反序列化的過程,創建一個對象輸入流,調用readObject()函數

 

例子:

package Note;

import java.io.*;

/**
 * @author yintianhao
 * @createTime 20190218 21:46
 * @description 序列化
 */
public class People implements Serializable {
    //序列化id
    private static final long serialVersionUID = -5809782578272943999L;

    private int age;
    private String name;


    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 static void main(String[] args) throws IOException,ClassNotFoundException {
        //序列化
        People one = new People();
        one.setAge(5);
        one.setName("張三");
        ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream(new File("G:/test.txt")));
        stream.writeObject(one);
        stream.close();

        //反序列化
        ObjectInputStream stream1 = new ObjectInputStream(new FileInputStream(new File("G:/test.txt")));
        People two = (People) stream1.readObject();
        System.out.println("Name = "+two.getName()+"--age = "+two.getAge());
        stream1.close();
    }
}
Code

檢驗一下G盤是否有這個test.txt

 再看Console

 

 

 

那麼問題來了:serialVersionUID是幹啥的? 

看字面上的意思就是版本號嘛,那麼這個版本號是幹啥的呢

那麼就有必要了解一下序列化的過程了:

序列化操作的時候系統會把當前類的serialVersionUID寫入到序列化文件中,當反序列化時系統會去檢測文件中的serialVersionUID,判斷它是否與當前類的serialVersionUID一致,如果一致就說明序列化類的版本與當前類版本是一樣的,可以反序列化成功,否則失敗。

當然這裏是我自己指定的serialVersionUID,如果這裏我們不寫也是沒問題的,因爲如果我們自己沒定義serialVersionUID

jdk會自行給我們生成一個serialVersionUID,但是一般情況IDE會報個警告,不知道爲啥IDEA沒報,但是Eclipse是報了...

第一句是生成默認的版本ID,值爲

第二句是根據類的類名信息等生成的,值爲

 

但是如果我們不指定ID,那麼,如果我們修改了類中的信息,比如增加或者刪除某個屬性,那麼我們在反序列化之前的

對象的時候就會報錯,因爲這個修改後的類的serialVersionUID已經變了,所以不能反序列化第一次的對象

打個比方增加一個性別sex的選項,然後爲了驗證把之前的序列化的過程去掉,看改完後的這個能不能反序列化之前的

代碼如下:

package Note;

import java.io.*;

/**
 * @author yintianhao
 * @createTime 20190218 21:46
 * @description 序列化
 */
public class People implements Serializable {
    //序列化id

    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 static void main(String[] args) throws IOException,ClassNotFoundException {
       

        //反序列化
        ObjectInputStream stream1 = new ObjectInputStream(new FileInputStream(new File("G:/test.txt")));
        People two = (People) stream1.readObject();
        System.out.println("Name = "+two.getName()+"--age = "+two.getAge());
        stream1.close();
    }
}
Code

運行,就報錯了

Exception in thread "main" java.io.InvalidClassException: Note.People; local class incompatible: stream classdesc serialVersionUID = 8716394284034362776, local class serialVersionUID = 5389077117487999490
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at Note.People.main(People.java:37)

 

這裏這個ID是由JDK的生成的,根據類的一些細節信息生成,具體怎麼生成的我們不管,但是像剛纔那樣我們是不願看見的,因爲不同的Java編譯器可能生成的

ID就不一樣,所以還是強烈建議自定義一個明確的serialVersionUID

 

參考博客:https://www.cnblogs.com/xdp-gacl/p/3777987.html

https://www.cnblogs.com/duanxz/p/3511695.html

 

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