<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-d7e2a68c7c.css">
<div class="htmledit_views" id="content_views">
導讀:最近在做項目的過程中,發現一個問題,就是我們最開始的時候,傳遞參數包括返回類型,都有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開始就有了,經過了長時間的考驗,性能上可能不是最好的,但它的穩定性絕對是值得肯定的。那么,其實在使用的時候,還是根據自身的情況考慮吧。在技術乃至於架構或者說各種系統設計,最實用最適合的,才是最好了!
其實我還有一個問題,不見得自己模塊會和數據庫部署到同一個機器上啊,所以還是得考慮都傳輸時的序列化問題,那如果使用第三方的工具,不都得來那么一波嘛,這代碼量就又活生生的多了那么點兒。唉,不說了,我這是越說越暈,回家吃飯!