javaBean需要實現Serializable接口的原因

引用:http://jzinfo.javaeye.com/blog/519470

 

Java的"對象序列化"能讓你將一個實現了Serializable接口的對象轉換成一組byte,這樣日後要用這個對象時候,你就能把這些byte數據恢復出來,並據此重新構建那個對象了。這一點甚至在跨網絡的環境下也是如此,這就意味着序列化機制能自動補償操作系統方面的差異。也就是說,你可以在Windows機器上創鍵一個對象,序列化之後,再通過網絡傳到Unix機器上,然後在那裏進行重建。你不用擔心在不同的平臺上數據是怎樣表示的,byte順序怎樣,或者別的什麼細節。

 

對象序列化本身就非常有趣,因爲它能讓你實現"輕量級的persistence(lightweight persistence)"。所謂persistence是指,對象的生命週期不是由程序是否運行決定的;在程序的兩次調用之間對象仍然還活着。通過"將做過序列化處理的對象寫入磁盤,等到程序再次運行的時候再把它讀出來",你可以達到persistence的效果。之所以說"輕量級",是因爲你不能用像"persistent"這樣的關鍵詞來直接定義一個對象,然後讓系統去處理所有細節(雖然將來有可能會這樣)。相反,你必須明確地進行序列化(serialize)和解序列化(deserialize)。如果你需要更爲正式的persistence功能,可以考慮Java Data Object( 簡稱是JDO)或Hibernate之類的工具(http://hibernate.sourceforge.net)。

 

之所以要在語言里加入對象序列化是因爲要用它來實現兩個重要的功能。Java的遠程方法調用(Remote Method Invocation簡稱RMI)能讓你像調用自己機器上的對象那樣去調用其它機器上的對象。當你向遠程對象傳遞消息的時候,就需通過對象序列化來傳送參數和返回值了。RMI會在Thinking in Enterprise Java作討論。

我們會在第14章講到JavaBean。對JavaBean來說,對象序列化也是必不可少的。Bean的狀態信息通常是在設計時配置的。這些狀態信息必須保存起來,供程序啓動的時候用;對象序列化就負責這個工作。

序列化一個對象還是比較簡單的,只要讓它實現Serializable接口就行了(這是一個"標記接口(tagging interface)",沒有任何方法)。但是,當語言引入序列化概念之後,它的很多標準類庫的類,包括primitive的wrapper類,所有的容器類,以及別的很多類,都會相應地發生改變。甚至連Class對象都會被序列化。

 

要想序列化對象,你必須先創建一個OutputStream,然後把它嵌進ObjectOutputStream。這時,你就能用writeObject( )方法把對象寫入OutputStream了。讀的時候,你得把InputStream嵌到ObjectInputStream裏面,然後再調用readObject( )方法。不過這樣讀出來的,只是一個Object的reference,因此在用之前,還得先下傳。

 

對象序列化最聰明的一點是,它不僅能保存對象的副本,而且還會跟着對象裏面的reference,把它所引用的對象也保存起來,然後再繼續跟蹤那些對象的reference,以此類推。這種情形常被稱爲"單個對象所聯結的'對象網'"。這個機制所涵蓋的範圍不僅包括對象的成員數據,而且還包含數組裏面的reference。如果你要自己實現對象序列化的話,那麼編寫跟蹤這些鏈接的程序將會是一件非常痛苦的任務。但是,Java的對象序列化就能精確無誤地做到這一點,毫無疑問,它的遍歷算法是做過優化的。

 

---------------------------------------------------------------------

實現java.io.Serializable 接口的類是可序列化的。沒有實現此接口的類將不能使它們的任一狀態被序列化或逆序列化。

  序列化類的所有子類本身都是可序列化的。這個序列化接口沒有任何方法和域,僅用於標識序列化的語意。允許非序列化類的子類型序列化,子類型可以假定負責保存和恢復父類型的公有的、保護的和(如果可訪問)包的域的狀態。只要該類(擴展)有一個無參構造子,可初始化它的狀態,那麼子類型就可承擔上述職責。在這種情況下申明一個可序列化的類是一個錯誤。此錯誤將在運行時被檢測。就是可以把對象存到字節流,然後可以恢復!

  例如:Integer實現了Serializable,所以可以把一個Integer的對象用IO寫到文件裏,之後再可以從文件裏讀出,如你開始寫入的時候那個對象的intValue() 是5的話,那讀出來之後也是5。這一點體現了用序化類的作用,即用來傳送類的對象。

  當一個JavaBean在構造工具內被用戶化,並與其它Bean建立連接之後,它的所有狀態都應當可被保存,下一次被load進構造工具內或在運行時,就應當是上一次修改完的信息。爲了能做到這一點,要把Bean的某些字段的信息保存下來,在定義Bean時要使它實現Java.io.Serializable接口。例如:

  public class Button implements Java.io.Serializable {……}

  實現了序列化接口的Bean中字段的信息將被自動保存。若不想保存某些字(這裏的Bean中字段的信息將被自動保存是什麼意思?這個自動保存是怎麼實現的?)

  段的信息則可在這些字段前冠以transient或static關鍵字,transient和static變量的信息是不可被保存的。通常,一個Bean所有公開出來的屬性都應當是被保存的,也可有選擇地保存內部狀態。Bean開發者在修改軟件時,可以添加字段,移走對其它類的引用,改變一個字段的private、protected或public狀態,這些都不影響類的存儲結構關係。然而,當從類中刪除一個字段,改變一個變量在類體系中的位置,把某個字段改成transient/static,或原來是transient/static,現改爲別的特性時,都將引起存儲關係的變化。

  所謂的Serializable,就是java提供的通用數據保存和讀取的接口。至於從什麼地方讀出來和保存到哪裏去都被隱藏在函數參數的背後了。這樣子,任何類型只要實現了Serializable接口,就可以被保存到文件中,或者作爲數據流通過網絡發送到別的地方。也可以用管道來傳輸到系統的其他程序中。這樣子極大的簡化了類的設計。只要設計一個保存一個讀取功能就能解決上面說得所有問題。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章