1、什么是序列化
Java是面向對象的編程語言,有時需要保存對象,並在下次使用時可以順利還原該對象。由於這種需求很常見,所以Java API對此提供了支持,添加相關程序代碼到標准類庫中,並將保存和還原的過程稱之為“對象序列化”。
Java SE7 文檔中將與對象序列化的相關內容做了詳細表述,將其稱為:
“Java對象序列化規范” Java Object Serialization Specification,網址為:
http://docs.oracle.com/javase/7/docs/platform/serialization/spec/serialTOC.html
2、為什么叫序列化
個人猜測:
由於保存對象的過程,是把對象保存為一連串字節流,而英文Serialization的意思“序列化”,所以序列化形象的表述了這個過程。
3、序列化保存那些內容
對象(object)是類(class)的一個實例(instance)。一個類中包含了變量(field)和函數(method)兩個部分。同一個 類的不同對象只是變量不同,所以Java API序列化過程中只保存了對象的變量部分。同樣,由於靜態變量(static field)是由同一個類的各個對象共用的,所以序列化過程中也不保存。
由於還原對象時需要在程序中動態創建該對象,所以程序也需要知道該對象的類定義,所以如果對象由一個程序序列化保存之后,由另外一個程序反序列化還原 時,類文件也需要傳送給該程序。這就需要擴展Java API序列化的功能,對其進行自定義。Java的遠程方法調用(Remote Method Invocation, RMI)功能,就是以Java API序列化為基礎,並進行了擴展。
3、序列化的用途
序列化主要有三個用途:
-
對象持久化(persistence)
對象持久化是指延長對象的存在時間。通常狀況下,當程序結束時,程序中的對象不再存在。
如果通過序列化功能,將對象保存到文件中,就可以延長對象的存在時間,在下次程序運行是再恢復該對象。
序列化將對象保存在文件中,是實現對象持久化的一種方式。持久化還有很多種方式,比如Hibernate框架就提供了一整套對象持久化的方案。
-
對象復制
通過序列化,將對象保存在內存中,可以再通過此數據得到多個對象的副本。
-
對象傳輸
通過序列化,將對象轉化字節流后,可以通過網絡發送給另外的Java程序。
4、什么是流(Stream)
Java是面向對象的編程語言,對象是對現實實體的抽象表述。所以Java API中流(Stream)是對一連串數據的抽象,同時定義了一些操作,write和read等。所以現實實體,只要包含數據和對數據的讀寫操作都可以表 示為流。OutputStream類和InputStream類,是2個抽象類,分別對應輸出、輸入流,所有其它流對象,都是其子類。
比如文件,文件本質是保存在存儲設備中的一連串數據,在Java API中抽象為FileOutputStream類和FileInputStream類,文件的讀寫可以通過對相應流的讀寫實現的。
比如控制台中命令和結果的輸入輸出,鍵盤的輸入是一串數據,程序的輸出是一串數據,所以在Java API中也被抽象為流對象。控制台輸入由System.in對象體現,System.in是類型為InputStream的對象。控制台輸出由 System.out對象體現,System.out是類型為PrintStream的對象。
由於文件和控制台輸入輸出都和操作系統有關,所以文件流和控制台流對象最終都是由Java虛擬機創建的。
ByteArrayOutputStream、ByteArrayInputStream,是完全不依賴Java虛擬機的流對象,其完全是對一個 byte[]數組的抽象。因為byte[]數組也是一連串數據,byte[]數組支持讀寫功能,所以完全可以抽象為流對象,這可以從這兩個類的源代碼中看 出。
4、使用序列化功能
在Java API中,對象序列化接口主要由兩個類提供:ObjectOutputStream,ObjectInputStream。
為了滿足保存到文件、內存、通過網絡傳輸等不同需求,對象序列化后保存在流對象中。提供不同的流對象時,序列化后保存在相應流對象中。比如提供 FileOutputStream和FileInputStream,就保存在文件中;提供ByteArrayOutputStream、 ByteArrayInputStream,就保存在內存中。
由於Java API已經提供了實現序列化需要的相關代碼,所以大部分情況下,使用序列化很簡單。例如:
保存對象:
1
2
3
4
5
6
|
//創建一個流對象,比如文件輸出流對象
FileOutputStream underlyingStream = new FileOutputStream( "C:\\temp\\test" );
//用剛才的文件流,創建一個對象序列化輸出流
ObjectOutputStream serializer = new ObjectOutputStream(underlyingStream);
//使用該流的輸出函數,將對象序列化后保存到文件流中,也就是保存到了對應文件中。
serializer.writeObject(serializableObject);
|
讀取對象,操作完全與保存是一一對應:
1
2
3
4
5
6
|
//創建一個流對象,比如文件輸入流對象
FileInputStream underlyingStream = new FileInputStream( "C:\\temp\\test" );
//用剛才的文件流,創建一個對象序列化輸入流
ObjectInputStream deserializer = new ObjectInputStream(underlyingStream);
//使用該流的輸入函數,將文件中保存的對象讀取到內存中,並創建相應對象。
Object deserializedObject = deserializer.readObject( );
|
5、什么樣的類可以序列化
不是所有的類都有序列化的必要,比如Thread類等,這些類中並沒有必要保存的信息。這也是序列化沒有成為Java內部功能的原因之一。所以,如果某個類需要序列化功能,類的定義中必須實現Serializable或者Externalizable接口。
比如Java API中的Character類:
1
2
|
public final
class Character implements java.io.Serializable, Comparable<Character>
|