1. 程式人生 > >JAVA序列化和發序列化

JAVA序列化和發序列化

1、什麼是序列化和反序列化

序列化:物件序列化的最主要的用處就是在傳遞和儲存物件的時候,保證物件的完整性和可傳遞性。序列化是把物件轉換成有序位元組流,以便在網路上傳輸或者儲存在本地檔案中。序列化後的位元組流儲存了Java物件的狀態以及相關的描述資訊。序列化機制的核心作用就是物件狀態的儲存與重建。

反序列化:客戶端從檔案中或網路上獲得序列化後的物件位元組流後,根據位元組流中所儲存的物件狀態及描述資訊,通過反序列化重建物件。 

2、為什麼需要序列化與反序列化 

當兩個程序在進行遠端通訊時,彼此可以傳送各種型別的資料。無論是何種型別的資料,都會以二進位制序列的形式在網路上傳送。傳送方需要把這個物件轉換為位元組序列,才能在網路上傳送;接收方則需要把位元組序列再恢復為物件。其實序列化的目的就是跨程序傳遞格式化資料 

3、如何實現序列化與發序列化 

只有實現了Serializable和Externalizable介面的類的物件才能被序列化。然後j通過ObjectOutputStream的writeObject方法可對引數指定的obj物件進行序列化,把得到的位元組序列寫到一個目標輸出流中。通過jObjectInputStream的readObject()方法從一個源輸入流中讀取位元組序列,再把它們反序列化為一個物件,並將其返回。那我們先寫個Demo,程式碼如下:

public class Student implements Serializable {
    private static final long serialVersionUID =1l;
    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 TestSerializeAndDeserialize {
    public static void main(String[] args) throws Exception {

        SerializePerson();
        Student stu=DeserializePerson();
        System.out.println(stu.getName()+" "+stu.getSex()+" "+stu.getAge());
    }

    private static void SerializePerson() throws IOException {
        Student stu=new Student();
        stu.setAge(10);
        stu.setName("xiaoming");
        stu.setSex("man");
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File("E:/Student.txt")));
        oos.writeObject(stu);
        System.out.println("Student物件序列化成功");
        oos.close();
    }
    private static Student DeserializePerson()throws Exception,IOException{
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("E:/Student.txt")));
        Student stu=(Student)ois.readObject();
        System.out.println("Student物件反序列化成功");
        return stu;
    }
}

程式執行結果:

 4.serialVersionUID的作用

s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D​:​ ​序​列​化​的​版​本​號​,凡是實現Serializable介面的類都應有一個表示序列化版本識別符號的靜態變數。如果沒有s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D會怎麼樣,我們去掉s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D後再執行程式結果如下:

下面我們在Student類新添一個score屬性,如下:

然後執行反序列操作,此時就會丟擲如下的異常資訊:

Exception in thread "main" java.io.InvalidClassException: com.lg.match.Student;
local class incompatible: stream classdesc serialVersionUID = -379872992605699466, 
local class serialVersionUID = 8365482709425766029

 如果新增s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D,再執行上面操作,執行結果如下:

serialVersionUID的取值是Java執行時環境根據類的內部細節自動生成的。如果對類的原始碼作了修改,再重新編譯,新生成的類檔案的serialVersionUID的取值有可能也會發生變化。類的serialVersionUID的預設值完全依賴於Java編譯器的實現,對於同一個類,用不同的Java編譯器編譯,有可能會導致不同的 serialVersionUID,也有可能相同。為了提高serialVersionUID的獨立性和確定性,強烈建議在一個可序列化類中顯示的定義serialVersionUID,為它賦予明確的值。
顯式地定義serialVersionUID有兩種用途:
         1、 在某些場合,希望類的不同版本對序列化相容,因此需要確保類的不同版本具有相同的serialVersionUID;
         2、 在某些場合,不希望類的不同版本對序列化相容,因此需要確保類的不同版本具有不同的serialVersionUID。