一、串行化的概念和目的
1.什么是串行化
對象的壽命通常隨著生成該對象的程序的終止而終止。有時候,可能需要將對象的狀態(tài)保存下來,在需要時再將對象恢復。我們把對象的這種能記錄自己的狀態(tài)以便將來再生的能力。叫作對象的持續(xù)性(persistence)。對象通過寫出描述自己狀態(tài)的數(shù)值來記錄自己 ,這個過程叫對象的串行化(Serialization) 。串行化的主要任務是寫出對象實例變量的數(shù)值。如果交量是另一對象的引用,則引用的對象也要串行化。這個過程是遞歸的,串行化可能要涉及一個復雜樹結構的單行化,包括原有對象、對象的對象、對象的對象的對象等等。對象所有權的層次結構稱為圖表(graph)。
2.串行化的目的
Java對象的單行化的目標是為Java的運行環(huán)境提供一組特性,如下所示:
1) 盡量保持對象串行化的簡單扼要 ,但要提供一種途徑使其可根據(jù)開發(fā)者的要求進行擴展或定制。
2) 串行化機制應嚴格遵守Java的對象模型 。對象的串行化狀態(tài)中應該存有所有的關于種類的安全特性的信息。
3) 對象的串行化機制應支持Java的對象持續(xù)性。
4) 對象的串行化機制應有足夠的 可擴展能力以支持對象的遠程方法調(diào)用(RMI)。
5) 對象串行化應允許對象定義自身 的格式即其自身的數(shù)據(jù)流表示形式,可外部化接口來完成這項功能。
二、串行化方法
從JDK1.1開始,Java語言提供了對象串行化機制 ,在java.io包中,接口Serialization用來作為實現(xiàn)對象串行化的工具 ,只有實現(xiàn)了Serialization的類的對象才可以被串行化。
Serializable接口中沒有任何的方法。當一個類聲明要實現(xiàn)Serializable接口時,只是表明該類參加串行化協(xié)議,而不需要實現(xiàn)任何特殊的方法。下面我們通過實例介紹如何對對象進行串行化。
1.定義一個可串行化對象
一個類,如果要使其對象可以被串行化,必須實現(xiàn)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.構造對象的輸入/輸出流
要串行化一個對象,必須與一定的對象輸出/輸入流聯(lián)系起來,通過對象輸出流將對象狀態(tài)保存下來,再通過對象輸入流將對象狀態(tài)恢復。
java.io包中,提供了ObjectInputStream和ObjectOutputStream將數(shù)據(jù)流功能擴展至可讀寫對象 。在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,實現(xiàn)了Serializable接口 ,然后通過對象輸出流的writeObject()方法將Student對象保存到文件 data.ser中 。之后,通過對家輸入流的readObjcet()方法從文件data.ser中讀出保存下來的Student對象 。從運行結果可以看到,通過串行化機制,可以正確地保存和恢復對象的狀態(tài)。
三、串行化的注意事項
1.串行化能保存的元素
串行化只能保存對象的非靜態(tài)成員交量,不能保存任何的成員方法和靜態(tài)的成員變量,而且串行化保存的只是變量的值,對于變量的任何修飾符都不能保存。
2.transient關鍵字
對于某些類型的對象,其狀態(tài)是瞬時的,這樣的對象是無法保存其狀態(tài)的。例如一個Thread對象或一個FileInputStream對象 ,對于這些字段,我們必須用transient關鍵字標明,否則編譯器將報措。
另外 ,串行化可能涉及將對象存放到 磁盤上或在網(wǎng)絡上發(fā)達數(shù)據(jù),這時候就會產(chǎn)生安全問題。因為數(shù)據(jù)位于Java運行環(huán)境之外,不在Java安全機制的控制之中。對于這些需要保密的字段,不應保存在永久介質(zhì)中 ,或者不應簡單地不加處理地保存下來 ,為了保證安全性。應該在這些字段前加上transient關鍵字。
-----------------------------------------------------
Silence, the way to avoid many problems;
Smile, the way to solve many problems;