探秘序列化里面的小九九(一)—序列化概念

0、序言

今天第一次更新簡(jiǎn)書(shū)的博客,(心情那個(gè)忐忑?。┓窒硪粋€(gè)最近稍微了解的序列化的知識(shí)。

之前做一個(gè)Android實(shí)時(shí)推送的功能,是用傳統(tǒng)的Socket然后自定義協(xié)議的方式,非常難處理(不要問(wèn)我為什么用這種坑爹的方式,boss一句話,寶寶心里苦?。?/p>

baobao.png

,常常要處理復(fù)雜的數(shù)據(jù)解析,浪費(fèi)大量時(shí)間在處理數(shù)據(jù)的打包和解析。然后因?yàn)橐淮蚊嬖?,突然從面試官口中?tīng)到了Protobuf,突然發(fā)現(xiàn)世間居然還有這么好用的東西,于是鼓起勇氣研究起序列化協(xié)議的相關(guān)東西。


啰嗦這么多,正文開(kāi)始

1、基本概念

我們先了解一下基本的使用和概念。
Java中序列化的基本概念如下:

  1. 把對(duì)象轉(zhuǎn)換為字節(jié)序列的過(guò)程稱為對(duì)象的序列化
  2. 把字節(jié)序列恢復(fù)為對(duì)象的過(guò)程稱為對(duì)象的反序列化。

看這個(gè)等于沒(méi)說(shuō),其實(shí)我們可以看一個(gè)例子:

1.1 如何序列化呢?

老板讓收集用戶的個(gè)人信息,包含它的用戶名,密碼和年齡并傳上來(lái),于是,我們定義一個(gè)需要傳遞的對(duì)象如下:

import java.io.Serializable;   
class User implements Serializable {         
    public byte age = 24;          
    public String name;
    public String password;   
} 

如下的方式,調(diào)用Java本身的ObjectOutputStream就可以將Object輸出到流中,生成一個(gè)二進(jìn)制序列,完成序列化的操作,同樣的,反序列化就是調(diào)用ObjectInputStream對(duì)象的readObject方法。具體我就不再列例子了。

import java.io.FileOutputStream; 
import java.io.ObjectOutputStream; 
class Main {          
    public static void main(String[] args) {          
          FileOutputStream fos = new FileOutputStream("temp.out");                          
          ObjectOutputStream oos = new ObjectOutputStream(fos);                
          User user = new User();                
          oos.writeObject(user);                
          oos.flush();                
          oos.close();       
    }
} 

1.2 還能做什么?

作為一個(gè)通信協(xié)議,如果序列化只能這樣轉(zhuǎn)換,那遠(yuǎn)遠(yuǎn)不夠的。如何應(yīng)對(duì)產(chǎn)品或是老板無(wú)窮無(wú)盡的需求更改呢(你懂的!)

  • 安全性?。?!
    今天老板跟你說(shuō),“我們這些字段中的密碼不要傳輸吧,都能被解析這不是很不好嗎?”
    但是轉(zhuǎn)念一想,我不能刪除這個(gè)字段啊,我要在其他業(yè)務(wù)中用到這個(gè)字段呢,也不能再新建一個(gè)沒(méi)有密碼的類,這不是很沒(méi)必要嘛。
    不要方,我們可以給類定義一個(gè)含有transient關(guān)鍵字的字段。這個(gè)關(guān)鍵字賦值后的數(shù)據(jù),不會(huì)再序列化后出現(xiàn),同時(shí)反序列化也不會(huì)解析,麻麻再也不用擔(dān)心你網(wǎng)絡(luò)傳輸中會(huì)被截取了。
import java.io.Serializable;   
class User implements Serializable {         
    public byte age = 24;          
    public String name;
    public tranisent String password;   
} 
  • 兼容性
    老板的需求當(dāng)然不會(huì)停的咯,今天老板又來(lái)說(shuō)了,“這個(gè)年齡啊,還是用年份吧,把原來(lái)的刪了吧,之前版本的也要兼容”
    這時(shí)候你一臉蒙蔽,寫出了這樣子的版本
import java.io.Serializable;   
class User implements Serializable {         
    public int year = 1992;          
    public String name;
    public tranisent String password;   
} 

然后,你發(fā)現(xiàn)這個(gè)根本無(wú)法兼容舊版本!

這個(gè)時(shí)候的解決方案就是要用上serialVersionUID,只有使用了自己定義的serialVersionUID,才能使新版本兼容舊版本。

1.3 其他的坑在哪里?

老板給你的需求越來(lái)越大,你這個(gè)數(shù)據(jù)類也會(huì)越來(lái)越復(fù)雜,你會(huì)開(kāi)始繼承父類,開(kāi)始定義其他的數(shù)據(jù),這個(gè)時(shí)候需要注意下面幾點(diǎn):

  1. 要想將父類對(duì)象也序列化,就需要讓父類也實(shí)現(xiàn)Serializable 接口。如果父類不實(shí)現(xiàn)的話的,就需要有默認(rèn)的無(wú)參的構(gòu)造函數(shù)。
  2. 序列化不保存靜態(tài)變量,因?yàn)殪o態(tài)變量是屬于類的狀態(tài),在程序開(kāi)啟時(shí)會(huì)統(tǒng)一加載。
  3. 如果你想自己定義序列化的規(guī)則,可以使用Externalizable
class User implements Externalizable{         
    int year = 1992;          
    String name;
    String password;   

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
       out.writeObject(name);
       out.writeInt(age);
    }
     
     @Override
     public void readExternal(ObjectIntput intput) throws IOException{
          this.name = (String) in.readObject();
          this.age = in.readInt();
     }
} 

注意: Externalizable會(huì)將tranisent 的關(guān)鍵字的信息屏蔽掉其功能,如果使用了Externalizable就不要使用tranisent關(guān)鍵字。


暫時(shí)介紹序列化的概念,下一篇文章介紹一下protobuf的相關(guān)知識(shí)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • JAVA序列化機(jī)制的深入研究 對(duì)象序列化的最主要的用處就是在傳遞,和保存對(duì)象(object)的時(shí)候,保證對(duì)象的完整...
    時(shí)待吾閱讀 10,908評(píng)論 0 24
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,868評(píng)論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,754評(píng)論 18 399
  • 官方文檔理解 要使類的成員變量可以序列化和反序列化,必須實(shí)現(xiàn)Serializable接口。任何可序列化類的子類都是...
    獅_子歌歌閱讀 2,434評(píng)論 1 3
  • 白天我和男朋友去逛街,想到我的眉筆用完了。就準(zhǔn)備買一支。挑來(lái)挑去就沒(méi)看到適合我的顏色,男友等得不耐煩了,就說(shuō)到,這...
    番茄愛(ài)上西紅柿123閱讀 166評(píng)論 0 0