1. 程式人生 > >Java中物件的序列化

Java中物件的序列化

今天在網上轉,偶爾看到有關序列化一篇文章,感覺不錯,稍加整理,轉了過來,以備後用。
原帖:[url]http://hi.baidu.com/qxmin1984/blog/item/0b84279028e46189a877a416.html[/url]
物件的序列化(Serialization) 一、序列化的概念和目的

1.什麼是序列化

物件的壽命通常隨著生成該物件的程式的終止而終止。有時候,可能需要將物件的狀態儲存下來,在需要時再將物件恢復。我們把物件的這種能記錄自己的狀態以便將來再生的能力。叫作物件的持續性(persistence)。物件通過寫出描述自己狀態的數值來記錄自己 ,這個過程叫物件的序列化(Serialization) 。序列化的主要任務是寫出物件例項變數的數值。如果交量是另一物件的引用,則引用的物件也要序列化。這個過程是遞迴的,序列化可能要涉及一個複雜樹結構的單行化,包括原有物件、物件的物件、物件的物件的物件等等。物件所有權的層次結構稱為圖表(graph)。

2.序列化的目的

Java物件的單行化的目標是為Java的執行環境提供一組特性,如下所示:

1) 儘量保持物件序列化的簡單扼要 ,但要提供一種途徑使其可根據開發者的要求進行擴充套件或定製。

2) 序列化機制應嚴格遵守Java的物件模型 。物件的序列化狀態中應該存有所有的關於種類的安全特性的資訊。

3) 物件的序列化機制應支援Java的物件持續性。

4) 物件的序列化機制應有足夠的 可擴充套件能力以支援物件的遠端方法呼叫(RMI)。

5) 物件序列化應允許物件定義自身 的格式即其自身的資料流表示形式,可外部化介面來完成這項功能。

二、序列化方法
從JDK1.1開始,Java語言提供了物件序列化機制 ,在java.io包中,介面Serialization用來作為實現物件序列化的工具 ,只有實現了Serialization的類的物件才可以被序列化。

Serializable介面中沒有任何的方法。當一個類宣告要實現Serializable介面時,只是表明該類參加序列化協議,而不需要實現任何特殊的方法。下面我們通過例項介紹如何對物件進行序列化。

1.定義一個可序列化物件

一個類,如果要使其物件可以被序列化,必須實現Serializable介面。我們定義一個類Student如下:

import java.io.Serializable;

public class Student implements Serializable {

int id;// 學號

String name;// 姓名

int age;// 年齡

String department; // 系別

public Student(int id, String name, int age, String department) {

this.id = id;

this.name = name;

this.age = age;

this.department = department;

}

}

2.構造物件的輸入/輸出流

要序列化一個物件,必須與一定的物件輸出/輸入流聯絡起來,通過物件輸出流將物件狀態儲存下來,再通過物件輸入流將物件狀態恢復。

java.io包中,提供了ObjectInputStream和ObjectOutputStream將資料流功能擴充套件至可讀寫物件 。在ObjectInputStream 中用readObject()方法可以直接讀取一個物件,ObjectOutputStream中用writeObject()方法可以直接將物件儲存到輸出流中。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class ObjectSer {

public static void main(String args[]) throws IOException,
ClassNotFoundException {

Student stu = new Student(981036, "LiuMing", 18, "CSD");

FileOutputStream fo = new FileOutputStream("data.ser");

ObjectOutputStream so = new ObjectOutputStream(fo);

try {

so.writeObject(stu);

so.close();

} catch (IOException e) {
System.out.println(e);
}

stu = null;

FileInputStream fi = new FileInputStream("data.ser");

ObjectInputStream si = new ObjectInputStream(fi);

try {

stu = (Student) si.readObject();

si.close();

} catch (IOException e)

{
System.out.println(e);
}

System.out.println("Student Info:");

System.out.println("ID:" + stu.id);

System.out.println("Name:" + stu.name);

System.out.println("Age:" + stu.age);

System.out.println("Dep:" + stu.department);

}

}

執行結果如下:


  Student Info:

  ID:981036

  Name:LiuMing

  Age:18

  Dep:CSD


在這個例子中,我們首先定義了一個類Student,實現了Seriali

zable介面 ,然後通過物件輸出流的writeObject()方法將Student物件儲存到檔案 data.ser中 。之後,通過對家輸入流的readObjcet()方法從檔案data.ser中讀出儲存下來的Student物件 。從執行結果可以看到,通過序列化機制,可以正確地儲存和恢復物件的狀態。

三、序列化的注意事項
1.序列化能儲存的元素

序列化只能儲存物件的非靜態成員交量,不能儲存任何的成員方法和靜態的成員變數,而且序列化儲存的只是變數的值,對於變數的任何修飾符都不能儲存。

2.transient關鍵字

對於某些型別的物件,其狀態是瞬時的,這樣的物件是無法儲存其狀態的。例如一個Thread物件或一個FileInputStream物件 ,對於這些欄位,我們必須用transient關鍵字標明,否則編譯器將報措。

另外 ,序列化可能涉及將物件存放到 磁碟上或在網路上發達資料,這時候就會產生安全問題。因為資料位於Java執行環境之外,不在Java安全機制的控制之中。對於這些需要保密的欄位,不應儲存在永久介質中 ,或者不應簡單地不加處理地儲存下來 ,為了保證安全性。應該在這些欄位前加上transient關鍵字。