1. 程式人生 > >java 序列化(serialization)演算法的透露

java 序列化(serialization)演算法的透露

宣告
[quote]原文出處:http://www.javaworld.com/community/node/2915
Submitted by javatips on Thu, 05/07/2009 - 15:28
[/quote]
序列化是將物件狀態儲存到位元組佇列的過程。
反序列化是:將這些位元組佇列轉換為一個活生生物件的過程。java 序列化的api為開發者處理序列化提供了一套標準的方法。在這個話題中,你將看到將怎麼去序列化一個物件。為什麼有時候序列化是必須的呢?你將學習到序列化演算法在java中的應用,緊接著你將看到一個被編排序列化的並且有插圖的物件。你到目前為至你應該對序列化演算法的工作和實體被序列化(作為物件的一部分)有一點了解吧

[b]為什麼序列化是必須的[/b]
在今天的這個世界上,一個有代表性的公司有很多各種各樣的元件,在分散式系統之間和網路之間互動。在java中一切都由物件來表示,如果java中的兩個元件之間想互相交流,需要一種方法去交換資料,第一種方法是定義你的協議去轉換物件,意思就是接受者根據這條協議知道這是傳送者建立的物件,若是第三個元件加入進來就比較困難了。因此這兒需要一個通用的並且效率高元件之間的物件轉換協議,序列化的定義就是為了這個目的,java元件就是用這個協議來實現物件之間的轉換。
圖一:顯示了一個客戶端和伺服器端之間交流高階檢視,這有一個通過序列化實現客戶端到伺服器端物件之間的轉換。[img]http://www.javaworld.com/javaworld/jw-05-2009/images/jtip050709-fig1.gif[/img]

[b]怎麼去序列化一個物件[/b]
目的是序列化一個物件,首先你要確定類物件實現了java.io.Serializable藉口如下列表

Listing 1. Implementing Serializable
class TestSerial implements Serializable {
public byte version = 100;
public byte count = 0;
}

在listing1中你必須做的不同的是建立一個實現java.io.Serializable介面的正常類。這個介面就是一個標記性藉口哦,此介面斷言根本沒有任何方法,表明實現此介面的類將被序列化。

現在你已經建立了一個合格並且序列化的類,下一步是真正的去序列化這個物件,那就是呼叫java.io.ObjectOutputStream類的writeObject()方法,如下listing2
Listing 2. Calling writeObject()

public static void main(String args[]) throws IOException {
FileOutputStream fos = new FileOutputStream("temp.out");
ObjectOutputStream oos = new ObjectOutputStream(fos);
TestSerial ts = new TestSerial();
oos.writeObject(ts);
oos.flush();
oos.close();
}


在一個檔案中listing2中儲存的TestSerial 物件狀態,被temp.out.oos.writeObject(ts);方法呼叫,實際上是踢出了序列化演算法,這個演算法迴圈把物件寫到temp.out
在序列化檔案裡面重新建立物件,你需要僱用以下listing3的程式碼
Listing 3 recreating a serialized object

public static void main(String args[]) throws IOException {
FileInputStream fis = new FileInputStream("temp.out");
ObjectInputStream oin = new ObjectInputStream(fis);
TestSerial ts = (TestSerial) oin.readObject();
System.out.println("version="+ts.version);
}

在listing3 中呼叫oin.readObject();方法,物件的原型就會被複原,這個方法讀取我們先前建立活生生元素物件的複製品的物件的位元組,因為readObject()能夠讀取任何序列化物件,一個塑造物件的型別是必要的。執行這段程式碼將在控制檯輸出version=100;

[b]一個序列化格式的物件[/b]
序列化形式的物件看起來像什麼呢?回憶一下,在前面段落的簡單程式碼儲存了序列化形式的TestSerial的物件到temp.out。listing 4顯示了temp.out的內容,十六進位制顯示(你需要一個十六進位制的編輯器去檢視這些輸出的十六進位制)
listing 4 TestSerial物件的十六進位制形式如下:

AC ED 00 05 73 72 00 0A 53 65 72 69 61 6C 54 6573 74 A0 0C 34 00 FE B1 DD F9 02 00 02 42 00 0563 6F 75 6E 74 42 00 07 76 65 72 73 69 6F 6E 7870 00 64


如果你不太喜歡真實的TestSerial物件,那你就看只有兩種型別的數字,listing 5 如下

  public byte version = 100;	
public byte count = 0;


一個byte型別變數的大小是 1 byte,因此總大小是2個位元組,不過你要是在listing 4 中看序列化物件的大小的話,那就是51個位元組。令人驚訝的是這些額外的位元組是在那裡來的,他們存在的意義又是什麼,他們是通過序列化演算法生產出來的額,目的就是重新建立物件,在接下里的章節,你認真研究一下這些細節中的演算法

[b]java 序列化演算法[/b]

到目前為之你應該對對怎麼去序列化一個物件有了一個很好的瞭解,那這個過程是怎麼進行的?如下是一個通用的序列化演算法。
1.它寫出了類物件內部的元資料
2、它遞迴地寫出了從超級類到java.lang.Object 的描述。
3、一旦到它寫完了元資料的資訊,緊接著它就啟動關聯例項的真實資料,不過在此時,它的啟動來源與最頂層的超級類。
4、它就會去寫關聯這個例項的資料,從最小的超類到最大獲得類


[size=medium][b]翻譯中。。。。。。。。。。。。。。[/b][/size]