在講Serializable之前,來先科普一下。數據的最小單位是位元,而1個位元組(1Byte)即8個bit(位元),也就是像01010011。在ASCII編碼裡「A」這個字為65→01000001(二進位)。而我們在電腦與朋友打字聊天時,其實傳輸的文字都是01000001這種位元(序列化),但電腦自動幫我們轉換為對應的文字(反序列化)。對於位元、位元組、二進位等有興趣的人,可以看一下資料處理相關的教科書,像是「計算機概論」等。
以下分為幾個部份來講解
— — — — — 1.序列化與反序列化的用作
— — — — — 2.序列化的方式
— — — — —3.反序列化的問題
— — — — — 4.serialVersionUID序列化ID
1.序列化與反序列化的用作
透過上面的說明,我們知道在電腦與網路的世界中,所有的資訊都是由01010011等(位元)所組成,因此無論透過任何介質在傳輸資料時,都要先將資料轉換為(位元)。對於Java來說最小的單位就是類別class。因此Serializable就是將類別序列化,變成可傳輸的(位元)方式,再透過反序列化組合而成原本的形態。就像是我們對於電腦檔案的複製或搬移,如下圖:
小分享
1986年的電影「變蠅人」(The Fly),講述的是世界萬物都是由分子組成的,因此透過「電子傳送艙」將任何物體(包含人),先分解成分子後再傳輸到另一端組合回為原來物體型態的故事。這是不是與Serializable序列化與反序列化很像。
2.序列化的方式
Java中最小的單位是類別class,因此要將類別變成可序列化的方式,就是在類別class中,去implements Serializable既可。那麼,接下來是否要做任何的變動呢?
不、需、要
打開Serializable這個Interface去看,你會發現裡面完全空無一物。
Serializable就像是個Tag(標籤),只是告訴Java這個類別class是可以被序列化。即然類別class可被Serializable序列化,相反的就能夠被反序列化(還原)。進而的,也可以設為不可被序列化,以及部份序列化transient與自定序列化Externalizable等。
3.反序列化的問題
反序列化中,就是要將所讀回來的Object轉成原本的物件型態,除了類別class內容需要完全一致外,其類別class的名稱以及類別class所在的Package名稱也需要完全相同,若是不相同則會出現ClassNotFoundException的錯誤
此外,對於序列化ID也需要相同一致也才能進行反序列化。而當需確保序列化與反序列化的類別class內容為相同外,可以另外加上序列化ID,也就是serialVersionUID。
4.serialVersionUID序列化ID
其實在序列化時,Java本身就會自動的幫類別class加上一組序列化的ID,這組序列化ID為19位(最多)的Long型態數字,預設的序列化ID有分二種,我暫先稱為隱藏式與可見式。
隱藏式的序列化ID,在類別class設為Serializable序列化時,Java會依照類別class的內容自動產出一組序號做為序列化ID,除非程式報錯(例如序列化ID不同,否則將不會在程式碼中看到這組ID)。而有趣的是,經過實驗後,當二個類別class的內容、名稱、Package路徑都相同,但明明就是不同的類別class,其隱藏的序列化ID,預設也會一模一樣。
可見式的序列化ID,則是在class類別中加入private static final long serialVersionUID = 19位(最多)的Long型態數字; serialVersionUID若是選擇預設,則會預設為1L。
此外也可以選擇帶入Java自動生成的序列化ID。