1. 程式人生 > >對Java Serializable(序列化)的理解和總結(一)

對Java Serializable(序列化)的理解和總結(一)

導讀:最近在做專案的過程中,發現一個問題,就是我們最開始的時候,傳遞引數包括返回型別,都有map型別。但是由於map每次都要匹配key值,很麻煩。所以在之後就將引數傳遞和返回型別全都改成了實體bean,並且讓每個bean都實現了Serializable介面。然後,在這裡的時候,就有點疑惑。首先:為什麼要進行序列化;其次:每個實體bean都必須實現serializabel介面嗎?最後:我做一些專案的時候,沒有實現序列化,同樣沒什麼影響,然後現在做專案需要序列化,到底什麼時候應該進行序列化操作呢?

本篇文章,是我對於序列化這個話題的一點小小的思考,可能還不太成熟,請每一個路過的人不吝賜教,在此,先謝過了!

一、什麼是序列化

In computer science, in the context of data storage, serialization is the process of translating data structures or object state into a format that can be stored (for example, in a file or memory buffer, or transmitted across a network connection link) and reconstructed later in the same or another computer environment.[1] When the resulting series of bits is reread according to the serialization format, it can be used to create a semantically identical clone of the original object.

那我也有看過很多的部落格包括書,但是我之前其實一直不太理解這個序列化,雖然一直都在用。今天在看資料 的時候,發現導致這種現象的原因,可能是我之前看的一些介紹裡面,忽略了一個很關鍵的因素:object state info物件的狀態資訊 。也就是說,其實序列化,它是完整的儲存了某一狀態下的物件資訊,是一個整體,而不是零散的!我在一個IBM工程師的部落格裡面看到一個說法,我感覺對於我理解序列化很有幫助,他說序列化的過程,就是一個“freeze”的過程,它將一個物件freeze住,然後進行儲存,等到再次需要的時候,再將這個物件de-freeze就可以立即使用。


二、為什麼需要序列化

1,儲存物件在儲存介質中,以便在下次使用的時候,可以很快捷的重建一個副本。也就是When the resulting series of bits is reread according to the serialization format, it can be used to create a semantically identical clone of the original object.

問題:我沒有實現序列化的時候,我一樣可以存入到我的sqlserver或者MySQL、Oracle資料庫中啊,為什麼一定要序列化才能儲存呢????

2,便於資料傳輸,尤其是在遠端呼叫的時候!


三、到底什麼時候一定要序列化

結合到第二點的問題,就是說在我儲存的時候,不通過序列化也一樣完美儲存,為什麼要多此一舉?額,經過我閱讀文件和書籍,以及做專案的經驗總結(反正就是之前混跡在編碼中的一系列經驗總結),在儲存時需要序列化,這是肯定的。大家知道的是序列化是將物件進行流化儲存,我們有時候感覺自己在專案中並沒有進行序列化操作,也一樣是存進去了,那麼物件需要經過序列化才能儲存的說法,似乎從這兒就給閹割了。事實究竟是怎樣的呢?

首先看我們常用的資料型別類宣告:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence
   

public class Date implements java.io.Serializable, Cloneable, Comparable
   
而像其他int、long、boolean型別等,都是基本資料型別,資料庫裡面有與之對應的資料結構。從上面的類宣告來看,我們以為的沒有進行序列化,其實是在宣告的各個不同變數的時候,由具體的資料型別幫助我們實現了序列化操作。

拿到這兒的時候,就又有一個問題,既然實體類的變數都已經幫助我們實現了序列化,為什麼我們仍然要顯示的讓類實現serializable介面呢?

請注意我以上的說法:首先,序列化的目的有兩個,第一個是便於儲存,第二個是便於傳輸。我們一般的實體類不需要程式設計師再次實現序列化的時候,請想兩個問題:第一:儲存媒體裡面,是否是有其相對應的資料結構?第二:這個實體類,是否需要遠端傳輸(或者兩個不同系統甚至是分散式模組之間的呼叫)?

如果有注意觀察的話,發現序列化操作用於儲存時,一般是對於NoSql資料庫,而在使用Nosql資料庫進行儲存時,用“freeze”這個說法來理解是再恰當不過了,請在NoSql資料庫中,給我找出個varchar,int之類的資料結構出來? 如果沒有,但我們又確實需要進行儲存,那麼,此時程式設計師再不將物件進行序列化,更待何時?

備註:如果有人開啟過Serializable介面的原始碼,就會發現,這個介面其實是個空介面,那麼這個序列化操作,到底是由誰去實現了呢?其實,看一下介面的註釋說明就知道,當我們讓實體類實現Serializable介面時,其實是在告訴JVM此類可被序列化,可被預設的序列化機制序列化。

然後,需要說明的是,當我們在實體類宣告實現Serializable介面時,再次進行觀察,會發現這些類是需要被遠端呼叫的。也就是說需要或者可能需要被遠端呼叫,這就是序列化便於傳輸的用途。

慎重宣告:以上所有言論,都是本寶寶經過專案中的具體觀察,以及閱讀一些文章之後的所謂經驗之談,且看且見諒吧!


三、是否一定要實現Serializable介面序列化

上回說到了關於序列化的一些基本情況,那麼,接下來的一個問題是:如果我們要實現序列化操作,是否一定要通過實現Serializable介面的方式?PS:其實,我只是不明白,為什麼大家一提到序列化就說特別簡單,實現Serializable介面就OK了?我就一直在想,這是否是目前我們所能擁有的最佳選擇?

請大家先看一篇文章分析:https://github.com/eishay/jvm-serializers/wiki

文章說得很清楚,圖文並茂的,那麼多選擇,自己看著辦吧。不過我最近做的一個專案使用的是protostuff!


四、使用其他序列化實現的優缺點

誠如大家在第三節分享的連結文章所見,通過實現Serializable介面的方式去進行序列化操作,在效能上來講並不是最佳選擇。那麼,在效能考慮的情況下,很多人都會選擇其他更為高效率的產品替代serializable介面,現在問題來了:

1,如果我通過Serializable介面實現,那麼我只需要在類宣告時實現它即可

2,如果我通過其他方式實現,那麼我將不得不自己重寫工具類,不能再通過實現serializable介面的方式去進行序列化了。在使用上,大大的不怎麼方便!

PS:專案中總會用到個什麼redis,mongoDB啥的,其實每次存取都有那麼一個數據封裝處理的過程,額,也差不了這一點了。那麼有沒有現成的人家封裝好的呢?自己找吧,肯定是有的。其實,我就是不明白,如果是用了第三方的工具去實現序列化,那麼在序列化進行遠端呼叫的時候,到底應該在哪兒進行顯示的序列化或者反序列操作?我剛開始想在Dao層,但這樣子的話,自己模組操作不也得來那麼一波序列化反序列化操作嘛。因為我目前確實只是在從NoSql資料庫中存取資料時用到了第三方的序列化工具,而在遠端呼叫的時候,沒有啊!以前都是直接實現Serializable介面的,唉。。。。學藝不精啊!

跪求指點!!!!!


五、總結

其實,很長的一段時間裡,我一直以為java底層包自帶的方法一定會是最好的,包括各個框架,我都更願意去用它本身就有的工具。但是,可能那些自帶的方法,尤其是向Serializable介面,從jdk1.1開始就有了,經過了長時間的考驗,效能上可能不是最好的,但它的穩定性絕對是值得肯定的。那麼,其實在使用的時候,還是根據自身的情況考慮吧。在技術乃至於架構或者說各種系統設計,最實用最適合的,才是最好了!

其實我還有一個問題,不見得自己模組會和資料庫部署到同一個機器上啊,所以還是得考慮都傳輸時的序列化問題,那如果使用第三方的工具,不都得來那麼一波嘛,這程式碼量就又活生生的多了那麼點兒。唉,不說了,我這是越說越暈,回家吃飯!