一、什麼是序列化
Java是面向對象的編程語言,有時須要保存對象,並在下次使用時能夠順利還原該對象。因爲這種需求很常見,因此Java API對此提供了支持,添加相關程序代碼到標準類庫中,並將保存和還原的過程稱之爲「對象序列化」。
Java SE7 文檔中將與對象序列化的相關內容作了詳細表述,將其稱爲:
「Java對象序列化規範」 Java Object Serialization Specification,網址爲:
http://docs.oracle.com/javase/7/docs/platform/serialization/spec/serialTOC.html
二、爲何叫序列化
我的猜想:
因爲保存對象的過程,是把對象保存爲一連串字節流,而英文Serialization的意思「序列化」,因此序列化形象的表述了這個過程。
三、序列化保存那些內容
對象(object)是類(class)的一個實例(instance)。一個類中包含了變量(field)和函數(method)兩個部分。同一個類的不一樣對象只是變量不一樣,因此Java API序列化過程當中只保存了對象的變量部分。一樣,因爲靜態變量(static field)是由同一個類的各個對象共用的,因此序列化過程當中也不保存。
因爲還原對象時須要在程序中動態建立該對象,因此程序也須要知道該對象的類定義,因此若是對象由一個程序序列化保存以後,由另一個程序反序列化還原時,類文件也須要傳送給該程序。這就須要擴展Java API序列化的功能,對其進行自定義。Java的遠程方法調用(Remote Method Invocation, RMI)功能,就是以Java API序列化爲基礎,並進行了擴展。
三、序列化的用途
序列化主要有三個用途:
對象持久化是指延長對象的存在時間。一般情況下,當程序結束時,程序中的對象再也不存在。
若是經過序列化功能,將對象保存到文件中,就能夠延長對象的存在時間,在下次程序運行是再恢復該對象。
序列化將對象保存在文件中,是實現對象持久化的一種方式。持久化還有不少種方式,好比Hibernate框架就提供了一整套對象持久化的方案。
經過序列化,將對象保存在內存中,能夠再經過此數據獲得多個對象的副本。
經過序列化,將對象轉化字節流後,能夠經過網絡發送給另外的Java程序。
四、什麼是流(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[]數組支持讀寫功能,因此徹底能夠抽象爲流對象,這能夠從這兩個類的源代碼中看出。
四、使用序列化功能
在Java API中,對象序列化接口主要由兩個類提供:ObjectOutputStream,ObjectInputStream。
爲了知足保存到文件、內存、經過網絡傳輸等不一樣需求,對象序列化後保存在流對象中。提供不一樣的流對象時,序列化後保存在相應流對象中。好比提供FileOutputStream和FileInputStream,就保存在文件中;提供ByteArrayOutputStream、ByteArrayInputStream,就保存在內存中。
因爲Java API已經提供了實現序列化須要的相關代碼,因此大部分狀況下,使用序列化很簡單。例如:
保存對象:
//建立一個流對象,好比文件輸出流對象
FileOutputStream underlyingStream = new FileOutputStream("C:\\temp\\test");
//用剛纔的文件流,建立一個對象序列化輸出流
ObjectOutputStream serializer = new ObjectOutputStream(underlyingStream);
//使用該流的輸出函數,將對象序列化後保存到文件流中,也就是保存到了對應文件中。
serializer.writeObject(serializableObject);
讀取對象,操做徹底與保存是一一對應:
//建立一個流對象,好比文件輸入流對象
FileInputStream underlyingStream = new FileInputStream("C:\\temp\\test");
//用剛纔的文件流,建立一個對象序列化輸入流
ObjectInputStream deserializer = new ObjectInputStream(underlyingStream);
//使用該流的輸入函數,將文件中保存的對象讀取到內存中,並建立相應對象。
Object deserializedObject = deserializer.readObject( );
五、什麼樣的類能夠序列化
不是全部的類都有序列化的必要,好比Thread類等,這些類中並無必要保存的信息。這也是序列化沒有成爲Java內部功能的緣由之一。因此,若是某個類須要序列化功能,類的定義中必須實現Serializable或者Externalizable接口。
好比Java API中的Character類:
public final
class Character implements java.io.Serializable, Comparable<Character>
六、進一步的內容
進一步的內容好比transient關鍵字、自定義序列化機制、序列化版本控制等,請參考如下文章: html
Java RMI Chapter 10 Serialization By William Grosso http://oreilly.com/catalog/javarmi/chapter/ch10.html Discover the secrets of the Java Serialization API by Todd Greanier http://www.oracle.com/technetwork/articles/java/javaserial-1536170.html Ivor Horton's Beginning Java(Java 7 Edition By Ivor Horton) Chapter 12 Serializing Object http://cn.bing.com/search?q=beginning+java+java+7+edition&go=&qs=AS&form=QBRE&pq=beginning+java+java&sc=2-19&sp=1&sk=