1. 程式人生 > >java中序列化與反序列化

java中序列化與反序列化

       把物件轉換為位元組序列的過程稱為物件的序列化。
  把位元組序列恢復為物件的過程稱為物件的反序列化。
  物件的序列化主要有兩種用途:
  1) 把物件的位元組序列永久地儲存到硬碟上,通常存放在一個檔案中;
  2) 在網路上傳送物件的位元組序列。

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

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

s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D​:​ ​字​面​意​思​上​是​序​列​化​的​版​本​號​,凡是實現Serializable介面的類都有一個表示序列化版本識別符號的靜態變數。我麼你來看一下Serializable介面中關於s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D的介紹:

       它的大致意思就是,如果類實現了Seriable介面就是可序列化的類,系統會根據類中的屬性等等預設生成一個類的​序​列​化​的​版​本​號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,比如,即:

private static final long serialVersionUID = 42L;

      因為,如果不是顯式宣告,類的結構改變的時候,s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D就會改變,之前儲存的資料在反序列化回來的時候就會報錯,丟擲異常。

     新建一個實現Serializable介面的Persion序列化類,Persion.java 

import java.io.Serializable;

/**
 * <p>ClassName: Person<p>
 * <p>Description:測試物件序列化和反序列化<p>
 */
public class Person implements Serializable {

    /**
     * 序列化ID
     */
    private static final long serialVersionUID = -5809782578272943999L;
    private int age;
    private String name;
    private String sex;

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public String getSex() {
        return sex;
    }

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

    public void setName(String name) {
        this.name = name;
    }

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

測試一下,這個類的序列化與反序列化:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.MessageFormat;

/**
 * <p>ClassName: TestObjSerializeAndDeserialize<p>
 * <p>Description: 測試物件的序列化和反序列<p>
 */
public class TestObjSerializeAndDeserialize {

    public static void main(String[] args) throws Exception {
        SerializePerson();//序列化Person物件
        Person p = DeserializePerson();//反序列Perons物件
        System.out.println(MessageFormat.format("name={0},age={1},sex={2}",
                p.getName(), p.getAge(), p.getSex()));
    }

    /**
     * MethodName: SerializePerson
     * Description: 序列化Person物件
     * @author xudp
     * @throws FileNotFoundException
     * @throws IOException
     */
    private static void SerializePerson() throws FileNotFoundException,
            IOException {
        Person person = new Person();
        person.setName("gacl");
        person.setAge(25);
        person.setSex("man");
        // ObjectOutputStream 物件輸出流,將Person物件儲存到E盤的Person.txt檔案中,完成對Person物件的序列化操作
        ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
                new File("E:/Person.txt")));
        oo.writeObject(person);
        System.out.println("Person物件序列化成功!");
        oo.close();
    }

    /**
     * MethodName: DeserializePerson
     * Description: 反序列Perons物件
     * @author xudp
     * @return
     * @throws Exception
     * @throws IOException
     */
    private static Person DeserializePerson() throws Exception, IOException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                new File("E:/Person.txt")));
        Person person = (Person) ois.readObject();
        System.out.println("Person物件反序列化成功!");
        return person;
    }

}

編譯執行:

檢視E盤,多了一個Person.txt

註釋掉

//SerializePerson();//序列化Person物件

註釋掉

/private static final long serialVersionUID = -5809782578272943999L;

       編譯執行會報錯,丟擲異常,這是因為,寫入Person.txt檔案時s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D=-5809782578272943999L,系統預設的s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D=-7391400382246312552。

Exception in thread "main" java.io.InvalidClassException: 
    serial.Person; local class incompatible: 
    stream classdesc serialVersionUID = -5809782578272943999, 
    local class serialVersionUID = -7391400382246312552