1. 程式人生 > >Java-serializable序列化

Java-serializable序列化

序列化和反序列化的概念

把物件轉換為位元組序列的過程稱為物件的 序列化 —— ObjectOutputStream
把位元組序列恢復為物件的過程稱為物件的 反序列化 —— ObjectInputStream

java.io.ObjectOutputStream代表物件輸出流,它的writeObject(Objectobj)方法可對引數指定的obj物件進行序列化,把得到的位元組序列寫到一個目標輸出流中。
java.io.ObjectInputStream代表物件輸入流,它的readObject()方法從一個源輸入流中讀取位元組序列,再把它們反序列化為一個物件,並將其返回。

物件的序列化主要有兩種用途

1) 把物件的位元組序列永久地儲存到硬碟上,通常存放在一個檔案中;   
2) 在網路上傳送物件的位元組序列。

只有實現了 Serializable 和 Externalizable 介面的類的物件才能被序列化。
Externalizable介面繼承自Serializable介面,實現Externalizable介面的類完全由自身來控制序列化的行為,而僅實現Serializable介面的類可以採用預設的序列化方式 。

物件序列化包括如下步驟

1) 建立一個物件輸出流,它可以包裝一個其他型別的目標輸出流,如檔案輸出流;   
2) 通過物件輸出流的writeObject()方法寫物件。

物件反序列化的步驟如下

1) 建立一個物件輸入流,它可以包裝一個其他型別的源輸入流,如檔案輸入流;  
2) 通過物件輸入流的readObject()方法讀取物件。

例子

Person類

import java.io.Serializable;

/**
 * <p>ClassName: Person<p>
 * <p>Description:測試物件序列化和反序列化<p>
 * @author xudp
 * @version 1.0 V
 * @createTime 2014-6-9 下午02:33:25
 */
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; } }

序列化和反序列化Person類物件

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 {
   
    /**
     * MethodName: SerializePerson 
     * Description: 序列化Person物件
     * @throws FileNotFoundException
     * @throws IOException
     */
    private static void SerializePerson() throws FileNotFoundException,
            IOException {
        Person person = new Person();
        person.setName("CR7");
        person.setAge(33);
        person.setSex("男");
        
        // ObjectOutputStream 物件輸出流,將Person物件儲存到E盤的Person.txt檔案中,完成對Person物件的序列化操作
        ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
                new File("E:/Person.obj")));
        // 序列化
        oo.writeObject(person);
        
        System.out.println("Person物件序列化成功!");
        oo.close();
    }

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

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

}

SerialVersionUID

serialVersionUID的取值是Java執行時環境根據類的內部細節自動生成的。如果對類的原始碼作了修改,再重新編譯,新生成的類檔案的serialVersionUID的取值有可能也會發生變化。

類的serialVersionUID的預設值完全依賴於Java編譯器的實現,對於同一個類,用不同的Java編譯器編譯,有可能會導致不同的
serialVersionUID,也有可能相同。為了提高serialVersionUID的獨立性和確定性,強烈建議在一個可序列化類中顯示的定義serialVersionUID,為它賦予明確的值。

顯式地定義serialVersionUID有兩種用途

1、 在某些場合,希望類的不同版本對序列化相容,因此需要確保類的不同版本具有相同的serialVersionUID;
2、 在某些場合,不希望類的不同版本對序列化相容,因此需要確保類的不同版本具有不同的serialVersionUID。