天天看點

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的介紹:

java中序列化與反序列化

       它的大緻意思就是,如果類實作了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;
    }

}
           

編譯運作:

java中序列化與反序列化

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

java中序列化與反序列化

注釋掉

//SerializePerson();//序列化Person對象
           
java中序列化與反序列化

注釋掉

/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