所謂對象序列化就是將對象的狀態轉換成字節流,以后可以通過這些值再生成相同狀態的對象 。這個過程也可以通過網絡實現 , 可以先在Windows機器上創建一個對象,對其序列化,然后通過網絡發給一臺Unix機器,然后在那里準確無誤地重新“裝配” 。像RMI、Socket、JMS、EJB它們中的一種,彼此為什么能夠傳遞Java對象 , 當然都是對象序列化機制的功勞 。
Java對象序列化機制一般來講有兩種用途:
Java的JavaBeans: Bean的狀態信息通常是在設計時配置的,Bean的狀態信息必須被存起來,以便當程序運行時能恢復這些狀態信息 , 這需要將對象的狀態保存到文件中,而后能夠通過讀入對象狀態來重新構造對象 , 恢復程序狀態 。
RMI允許象在本機上一樣操作遠程機器上的對象;或使用套接字在網絡上傳送對象的程序來說 , 這些都是需要實現serializaiton機制的 。
我們通過讓類實現Java.io.Serializable 接口可以將類序列化 。這個接口是一個制造者(marker)接口 。也就是說 , 對于要實現它的類來說,該接口不需要實現任何方法 。它主要用來通知Java虛擬機(JVM),需要將一個對象序列化 。
對于這個 , 有幾點我們需要明確:
并非所有類都可以序列化,在cmd下,我們輸入serialver Java.net.Socket , 可以得到socket是否可序列化的信息,實際上socket是不可序列化的 。
Java有很多基礎類已經實現了serializable接口,比如string,vector等 。但是比如hashtable就沒有實現serializable接口 。
將對象讀出或者寫入流的主要類有兩個: ObjectOutputStream與ObjectInputStream .ObjectOutputStream 提供用來將對象寫入輸出流的writeObject方法,ObjectInputStream提供從輸入流中讀出對象的readObject方法 。使用這些方法的對象必須已經被序列化的 。也就是說 , 必須已經實現 Serializable接口 。如果你想writeobject一個hashtable對象,那么,會得到一個異常 。
序列化的過程就是對象寫入字節流和從字節流中讀取對象 。將對象狀態轉換成字節流之后 , 可以用Java.io包中的各種字節流類將其保存到文件中,管道到另一線程中或通過網絡連接將對象數據發送到另一主機 。對象序列化功能非常簡單、強大 , 在RMI、Socket、JMS、EJB都有應用 。對象序列化問題在網絡編程中并不是最激動人心的課題,但卻相當重要,具有許多實用意義 。
對象序列化可以實現分布式對象 。主要應用例如:RMI要利用對象序列化運行遠程主機上的服務,就像在本地機上運行對象時一樣 。
Java對象序列化不僅保留一個對象的數據,而且遞歸保存對象引用的每個對象的數據 。可以將整個對象層次寫入字節流中 , 可以保存在文件中或在網絡連接上傳遞 。利用對象序列化可以進行對象的“深復制”,即復制對象本身及引用的對象本身 。序列化一個對象可能得到整個對象序列 。
Java序列化比較簡單 , 通常不需要編寫保存和恢復對象狀態的定制代碼 。實現Java.io.Serializable接口的類對象可以轉換成字節流或從字節流恢復,不需要在類中增加任何代碼 。只有極少數情況下才需要定制代碼保存或恢復對象狀態 。這里要注意:不是每個類都可序列化 , 有些類是不能序列化的,例如涉及線程的類與特定JVM有非常復雜的關系 。
序列化機制:
序列化分為兩大部分:序列化 和反序列化。序列化是這個過程的第一部分 , 將數據分解成字節流,以便存儲在文件中或在網絡上傳輸 。反序列化就是打開字節流并重構對象 。對象序列化不僅要將基本數據類型轉換成字節表示 , 有時還要恢復數據 。恢復數據要求有恢復數據的對象實例 。ObjectOutputStream中的序列化過程與字節流連接,包括對象類型和版本信息 。反序列化時,JVM用頭信息生成對象實例,然后將對象字節流中的數據復制到對象數據成員中 。下面我們分兩大部分來闡述:
處理對象流:
?。ㄐ蛄謝毯頭蔥蛄謝蹋?
Java.io包有兩個序列化對象的類 。ObjectOutputStream負責將對象寫入字節流,ObjectInputStream從字節流重構對象 。
我們先了解ObjectOutputStream類吧 。ObjectOutputStream類擴展DataOutput接口 。
writeObject() 方法是最重要的方法,用于對象序列化 。如果對象包含其他對象的引用,則writeObject()方法遞歸序列化這些對象 。每個 ObjectOutputStream維護序列化的對象引用表,防止發送同一對象的多個拷貝 。(這點很重要)由于writeObject()可以序列化整組交叉引用的對象,因此同一ObjectOutputStream實例可能不小心被請求序列化同一對象 。這時,進行反引用序列化 , 而不是再次寫入對象字節流 。
【Java對象序列化的使用】
