Java序列化(Serialization)的理解


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>





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM