Java 序列化的高級(jí)認(rèn)識(shí)-[轉(zhuǎn)]

序言

將 Java 對(duì)象序列化為二進(jìn)制文件的 Java 序列化技術(shù)是 Java 系列技術(shù)中一個(gè)較為重要的技術(shù)點(diǎn)币叹,在大部分情況下锨苏,開發(fā)人員只需要了解被序列化的類需要實(shí)現(xiàn) Serializable 接口邑滨,使用 ObjectInputStream 和 ObjectOutputStream 進(jìn)行對(duì)象的讀寫。然而在有些情況下恼策,光知道這些還遠(yuǎn)遠(yuǎn)不夠咽块,文章列舉了筆者遇到的一些真實(shí)情境,它們與 Java 序列化相關(guān)腻惠,通過分析情境出現(xiàn)的原因环肘,使讀者輕松牢記 Java 序列化中的一些高級(jí)認(rèn)識(shí)。

序列化 ID 問題

情境:兩個(gè)客戶端 A 和 B 試圖通過網(wǎng)絡(luò)傳遞對(duì)象數(shù)據(jù)集灌,A 端將對(duì)象 C 序列化為二進(jìn)制數(shù)據(jù)再傳給 B悔雹,B 反序列化得到 C。

問題:C 對(duì)象的全類路徑假設(shè)為 com.inout.Test欣喧,在 A 和 B 端都有這么一個(gè)類文件腌零,功能代碼完全一致。也都實(shí)現(xiàn)了 Serializable 接口唆阿,但是反序列化時(shí)總是提示不成功益涧。

解決:虛擬機(jī)是否允許反序列化,不僅取決于類路徑和功能代碼是否一致驯鳖,一個(gè)非常重要的一點(diǎn)是兩個(gè)類的序列化 ID 是否一致(就是 private static final long serialVersionUID = 1L)闲询。清單 1 中,雖然兩個(gè)類的功能代碼完全一致浅辙,但是序列化 ID 不同扭弧,他們無(wú)法相互序列化和反序列化。

清單 1. 相同功能代碼不同序列化 ID 的類對(duì)比

 package com.inout; 

 import java.io.Serializable; 

 public class A implements Serializable { 

     private static final long serialVersionUID = 1L; 

     private String name; 
    
     public String getName() 
     { 
         return name; 
     } 
    
     public void setName(String name) 
     { 
         this.name = name; 
     } 
 } 

 package com.inout; 

 import java.io.Serializable; 

 public class A implements Serializable { 

     private static final long serialVersionUID = 2L; 
    
     private String name; 
    
     public String getName() 
     { 
         return name; 
     } 
    
     public void setName(String name) 
     { 
         this.name = name; 
     } 
 }

序列化 ID 在 Eclipse 下提供了兩種生成策略摔握,一個(gè)是固定的 1L寄狼,一個(gè)是隨機(jī)生成一個(gè)不重復(fù)的 long 類型數(shù)據(jù)(實(shí)際上是使用 JDK 工具生成),在這里有一個(gè)建議氨淌,如果沒有特殊需求泊愧,就是用默認(rèn)的 1L 就可以,這樣可以確保代碼一致時(shí)反序列化成功盛正。那么隨機(jī)生成的序列化 ID 有什么作用呢删咱,有些時(shí)候,通過改變序列化 ID 可以用來(lái)限制某些用戶的使用豪筝。

特性使用案例

讀者應(yīng)該聽過 Fa?ade 模式痰滋,它是為應(yīng)用程序提供統(tǒng)一的訪問接口,案例程序中的 Client 客戶端使用了該模式续崖,案例程序結(jié)構(gòu)圖如圖 1 所示敲街。
圖 1. 案例程序結(jié)構(gòu)


facade-object.gif

Client 端通過 Fa?ade Object 才可以與業(yè)務(wù)邏輯對(duì)象進(jìn)行交互。而客戶端的 Fa?ade Object 不能直接由 Client 生成严望,而是需要 Server 端生成多艇,然后序列化后通過網(wǎng)絡(luò)將二進(jìn)制對(duì)象數(shù)據(jù)傳給 Client,Client 負(fù)責(zé)反序列化得到 Fa?ade 對(duì)象像吻。該模式可以使得 Client 端程序的使用需要服務(wù)器端的許可峻黍,同時(shí) Client 端和服務(wù)器端的 Fa?ade Object 類需要保持一致复隆。當(dāng)服務(wù)器端想要進(jìn)行版本更新時(shí),只要將服務(wù)器端的 Fa?ade Object 類的序列化 ID 再次生成姆涩,當(dāng) Client 端反序列化 Fa?ade Object 就會(huì)失敗挽拂,也就是強(qiáng)制 Client 端從服務(wù)器端獲取最新程序。


靜態(tài)變量序列化

情境:查看清單 2 的代碼骨饿。

清單 2. 靜態(tài)變量序列化問題代碼
 public class Test implements Serializable {

    private static final long serialVersionUID = 1L;

    public static int staticVar = 5;

    public static void main(String[] args) {
        try {
            //初始時(shí)staticVar為5
            ObjectOutputStream out = new ObjectOutputStream(
                    new FileOutputStream("result.obj"));
            out.writeObject(new Test());
            out.close();

            //序列化后修改為10
            Test.staticVar = 10;

            ObjectInputStream oin = new ObjectInputStream(new FileInputStream(
                    "result.obj"));
            Test t = (Test) oin.readObject();
            oin.close();
            
            //再讀取亏栈,通過t.staticVar打印新的值
            System.out.println(t.staticVar);
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

清單 2 中的 main 方法,將對(duì)象序列化后样刷,修改靜態(tài)變量的數(shù)值仑扑,再將序列化對(duì)象讀取出來(lái),然后通過讀取出來(lái)的對(duì)象獲得靜態(tài)變量的數(shù)值并打印出來(lái)置鼻。依照清單 2镇饮,這個(gè) System.out.println(t.staticVar) 語(yǔ)句輸出的是 10 還是 5 呢?

最后的輸出是 10箕母,對(duì)于無(wú)法理解的讀者認(rèn)為储藐,打印的 staticVar 是從讀取的對(duì)象里獲得的,應(yīng)該是保存時(shí)的狀態(tài)才對(duì)嘶是。之所以打印 10 的原因在于序列化時(shí)钙勃,并不保存靜態(tài)變量,這其實(shí)比較容易理解聂喇,序列化保存的是對(duì)象的狀態(tài)辖源,靜態(tài)變量屬于類的狀態(tài),因此 序列化并不保存靜態(tài)變量希太。


父類的序列化與 Transient 關(guān)鍵字

情境:一個(gè)子類實(shí)現(xiàn)了 Serializable 接口克饶,它的父類都沒有實(shí)現(xiàn) Serializable 接口,序列化該子類對(duì)象誊辉,然后反序列化后輸出父類定義的某變量的數(shù)值矾湃,該變量數(shù)值與序列化時(shí)的數(shù)值不同。

解決:要想將父類對(duì)象也序列化堕澄,就需要讓父類也實(shí)現(xiàn)Serializable 接口邀跃。如果父類不實(shí)現(xiàn)的話,就需要有默認(rèn)的無(wú)參的構(gòu)造函數(shù)蛙紫。在父類沒有實(shí)現(xiàn) Serializable 接口時(shí)拍屑,虛擬機(jī)是不會(huì)序列化父對(duì)象的,而一個(gè) Java 對(duì)象的構(gòu)造必須先有父對(duì)象坑傅,才有子對(duì)象丽涩,反序列化也不例外。所以反序列化時(shí)裁蚁,為了構(gòu)造父對(duì)象矢渊,只能調(diào)用父類的無(wú)參構(gòu)造函數(shù)作為默認(rèn)的父對(duì)象。因此當(dāng)我們?nèi)「笇?duì)象的變量值時(shí)枉证,它的值是調(diào)用父類無(wú)參構(gòu)造函數(shù)后的值矮男。如果你考慮到這種序列化的情況,在父類無(wú)參構(gòu)造函數(shù)中對(duì)變量進(jìn)行初始化室谚,否則的話毡鉴,父類變量值都是默認(rèn)聲明的值,如 int 型的默認(rèn)是 0秒赤,string 型的默認(rèn)是 null猪瞬。

Transient 關(guān)鍵字的作用是控制變量的序列化,在變量聲明前加上該關(guān)鍵字入篮,可以阻止該變量被序列化到文件中陈瘦,在被反序列化后,transient 變量的值被設(shè)為初始值潮售,如 int 型的是 0痊项,對(duì)象型的是 null。

特性使用案例

我們熟悉使用 Transient 關(guān)鍵字可以使得字段不被序列化酥诽,那么還有別的方法嗎鞍泉?根據(jù)父類對(duì)象序列化的規(guī)則,我們可以將不需要被序列化的字段抽取出來(lái)放到父類中肮帐,子類實(shí)現(xiàn) Serializable 接口咖驮,父類不實(shí)現(xiàn),根據(jù)父類序列化規(guī)則训枢,父類的字段數(shù)據(jù)將不被序列化托修,形成類圖如圖 2 所示。


transient.gif

上圖中可以看出肮砾,attr1诀黍、attr2、attr3仗处、attr5 都不會(huì)被序列化眯勾,放在父類中的好處在于當(dāng)有另外一個(gè) Child 類時(shí),attr1婆誓、attr2吃环、attr3 依然不會(huì)被序列化,不用重復(fù)抒寫 transient洋幻,代碼簡(jiǎn)潔郁轻。


對(duì)敏感字段加密

情境:服務(wù)器端給客戶端發(fā)送序列化對(duì)象數(shù)據(jù),對(duì)象中有一些數(shù)據(jù)是敏感的,比如密碼字符串等好唯,希望對(duì)該密碼字段在序列化時(shí)竭沫,進(jìn)行加密,而客戶端如果擁有解密的密鑰骑篙,只有在客戶端進(jìn)行反序列化時(shí)蜕提,才可以對(duì)密碼進(jìn)行讀取,這樣可以一定程度保證序列化對(duì)象的數(shù)據(jù)安全靶端。

解決:在序列化過程中谎势,虛擬機(jī)會(huì)試圖調(diào)用對(duì)象類里的 writeObject 和 readObject 方法,進(jìn)行用戶自定義的序列化和反序列化杨名,如果沒有這樣的方法脏榆,則默認(rèn)調(diào)用是 ObjectOutputStream 的 defaultWriteObject 方法以及 ObjectInputStream 的 defaultReadObject 方法。用戶自定義的 writeObject 和 readObject 方法可以允許用戶控制序列化的過程台谍,比如可以在序列化的過程中動(dòng)態(tài)改變序列化的數(shù)值须喂。基于這個(gè)原理典唇,可以在實(shí)際應(yīng)用中得到使用镊折,用于敏感字段的加密工作,清單 3 展示了這個(gè)過程介衔。

 清單 3. 靜態(tài)變量序列化問題代碼
 private static final long serialVersionUID = 1L;

    private String password = "pass";

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    private void writeObject(ObjectOutputStream out) {
        try {
            PutField putFields = out.putFields();
            System.out.println("原密碼:" + password);
            password = "encryption";//模擬加密
            putFields.put("password", password);
            System.out.println("加密后的密碼" + password);
            out.writeFields();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void readObject(ObjectInputStream in) {
        try {
            GetField readFields = in.readFields();
            Object object = readFields.get("password", "");
            System.out.println("要解密的字符串:" + object.toString());
            password = "pass";//模擬解密,需要獲得本地的密鑰
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        try {
            ObjectOutputStream out = new ObjectOutputStream(
                    new FileOutputStream("result.obj"));
            out.writeObject(new Test());
            out.close();

            ObjectInputStream oin = new ObjectInputStream(new FileInputStream(
                    "result.obj"));
            Test t = (Test) oin.readObject();
            System.out.println("解密后的字符串:" + t.getPassword());
            oin.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

在清單 3 的 writeObject 方法中恨胚,對(duì)密碼進(jìn)行了加密,在 readObject 中則對(duì) password 進(jìn)行解密炎咖,只有擁有密鑰的客戶端赃泡,才可以正確的解析出密碼,確保了數(shù)據(jù)的安全乘盼。執(zhí)行清單 3 后控制臺(tái)輸出如圖 3 所示升熊。
圖 3. 數(shù)據(jù)加密演示


password.jpg

特性使用案例

RMI 技術(shù)是完全基于 Java 序列化技術(shù)的,服務(wù)器端接口調(diào)用所需要的參數(shù)對(duì)象來(lái)至于客戶端绸栅,它們通過網(wǎng)絡(luò)相互傳輸级野。這就涉及 RMI 的安全傳輸?shù)膯栴}。一些敏感的字段粹胯,如用戶名密碼(用戶登錄時(shí)需要對(duì)密碼進(jìn)行傳輸)蓖柔,我們希望對(duì)其進(jìn)行加密,這時(shí)风纠,就可以采用本節(jié)介紹的方法在客戶端對(duì)密碼進(jìn)行加密况鸣,服務(wù)器端進(jìn)行解密,確保數(shù)據(jù)傳輸?shù)陌踩浴?/p>


序列化存儲(chǔ)規(guī)則

情境:?jiǎn)栴}代碼如清單 4 所示竹观。

清單 4. 存儲(chǔ)規(guī)則問題代碼
 ObjectOutputStream out = new ObjectOutputStream(
                    new FileOutputStream("result.obj"));
    Test test = new Test();
    //試圖將對(duì)象兩次寫入文件
    out.writeObject(test);
    out.flush();
    System.out.println(new File("result.obj").length());
    out.writeObject(test);
    out.close();
    System.out.println(new File("result.obj").length());

    ObjectInputStream oin = new ObjectInputStream(new FileInputStream(
            "result.obj"));
    //從文件依次讀出兩個(gè)文件
    Test t1 = (Test) oin.readObject();
    Test t2 = (Test) oin.readObject();
    oin.close();
            
    //判斷兩個(gè)引用是否指向同一個(gè)對(duì)象
    System.out.println(t1 == t2);

清單 3 中對(duì)同一對(duì)象兩次寫入文件镐捧,打印出寫入一次對(duì)象后的存儲(chǔ)大小和寫入兩次后的存儲(chǔ)大小潜索,然后從文件中反序列化出兩個(gè)對(duì)象爱致,比較這兩個(gè)對(duì)象是否為同一對(duì)象洁仗。一般的思維是,兩次寫入對(duì)象龄糊,文件大小會(huì)變?yōu)閮杀兜拇笮⊥嫜妫葱蛄谢瘯r(shí)由驹,由于從文件讀取,生成了兩個(gè)對(duì)象昔园,判斷相等時(shí)應(yīng)該是輸入 false 才對(duì),但是最后結(jié)果輸出如圖 4 所示并炮。
圖 4. 示例程序輸出


save-rules.jpg

我們看到默刚,第二次寫入對(duì)象時(shí)文件只增加了 5 字節(jié),并且兩個(gè)對(duì)象是相等的逃魄,這是為什么呢荤西?
解答:Java 序列化機(jī)制為了節(jié)省磁盤空間,具有特定的存儲(chǔ)規(guī)則伍俘,當(dāng)寫入文件的為同一對(duì)象時(shí)邪锌,并不會(huì)再將對(duì)象的內(nèi)容進(jìn)行存儲(chǔ),而只是再次存儲(chǔ)一份引用癌瘾,上面增加的 5 字節(jié)的存儲(chǔ)空間就是新增引用和一些控制信息的空間觅丰。反序列化時(shí),恢復(fù)引用關(guān)系妨退,使得清單 3 中的 t1 和 t2 指向唯一的對(duì)象妇萄,二者相等,輸出 true咬荷。該存儲(chǔ)規(guī)則極大的節(jié)省了存儲(chǔ)空間冠句。

特性案例分析

查看清單 5 的代碼。

清單 5. 案例代碼
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("result.obj"));
Test test = new Test();
test.i = 1;
out.writeObject(test);
out.flush();
test.i = 2;
out.writeObject(test);
out.close();
ObjectInputStream oin = new ObjectInputStream(new FileInputStream(
                    "result.obj"));
Test t1 = (Test) oin.readObject();
Test t2 = (Test) oin.readObject();
System.out.println(t1.i);
System.out.println(t2.i);

清單 4 的目的是希望將 test 對(duì)象兩次保存到 result.obj 文件中幸乒,寫入一次以后修改對(duì)象屬性值再次保存第二次懦底,然后從 result.obj 中再依次讀出兩個(gè)對(duì)象,輸出這兩個(gè)對(duì)象的 i 屬性值罕扎。案例代碼的目的原本是希望一次性傳輸對(duì)象修改前后的狀態(tài)聚唐。

結(jié)果兩個(gè)輸出的都是 1, 原因就是第一次寫入對(duì)象以后壳影,第二次再試圖寫的時(shí)候拱层,虛擬機(jī)根據(jù)引用關(guān)系知道已經(jīng)有一個(gè)相同對(duì)象已經(jīng)寫入文件,因此只保存第二次寫的引用宴咧,所以讀取時(shí)根灯,都是第一次保存的對(duì)象。讀者在使用一個(gè)文件多次 writeObject 需要特別注意這個(gè)問題。

類實(shí)現(xiàn)Serializable 接口但類屬性對(duì)象實(shí)現(xiàn)該接口的問題「原創(chuàng)」

場(chǎng)景如下代碼所示:

public class A {}

import lombok.Data;
@Data
public class B implements Serializable {
 private static final long serialVersionUID = 1L; 
 private String name;
 private A a;
}

類A實(shí)現(xiàn)了Serializable 接口, 類A的屬性B沒有實(shí)現(xiàn)Serializable 接口烙肺,在序列化時(shí)纳猪,會(huì)報(bào)java.io.NotSerializableException異常;
因此類屬性也需要實(shí)現(xiàn)序列化桃笙,但基本類型則不用顯式實(shí)現(xiàn)呢氏堤?因?yàn)榛绢愋蛯?duì)象如Integer、String等已實(shí)現(xiàn)序列化搏明。

序列化反序列化中 如何防止破壞單例模式「原創(chuàng)」

答案是使用在類中使用readResovle方法,代碼如下

public final class MySingleton implements Serializable{
    private MySingleton() { }
    private static final MySingleton INSTANCE = new MySingleton();
    public static MySingleton getInstance() { return INSTANCE; }

    // readResolve method to preserve singleton property
    private Object readResolve()  {
       // instead of the object we're on,
       // return the class variable INSTANCE
      return INSTANCE;
   }
}

方法readResovle會(huì)在ObjectInputStream讀取一個(gè)對(duì)象并返回前調(diào)用鼠锈。如果定義了,會(huì)由readResovle指定返回的對(duì)象星著,返回的對(duì)象一定是要同類型對(duì)象购笆,否則會(huì)拋出ClassCastException。

Java 序列化的高級(jí)認(rèn)識(shí)-原文章鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末虚循,一起剝皮案震驚了整個(gè)濱河市同欠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌横缔,老刑警劉巖铺遂,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異茎刚,居然都是意外死亡襟锐,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門斗蒋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)捌斧,“玉大人,你說(shuō)我怎么就攤上這事泉沾±搪欤” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵跷究,是天一觀的道長(zhǎng)姓迅。 經(jīng)常有香客問我,道長(zhǎng)俊马,這世上最難降的妖魔是什么丁存? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮柴我,結(jié)果婚禮上解寝,老公的妹妹穿的比我還像新娘。我一直安慰自己艘儒,他們只是感情好聋伦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布夫偶。 她就那樣靜靜地躺著,像睡著了一般觉增。 火紅的嫁衣襯著肌膚如雪兵拢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天逾礁,我揣著相機(jī)與錄音说铃,去河邊找鬼。 笑死嘹履,一個(gè)胖子當(dāng)著我的面吹牛腻扇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播植捎,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼衙解,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了焰枢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤舌剂,失蹤者是張志新(化名)和其女友劉穎济锄,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霍转,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡荐绝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了避消。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片低滩。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖岩喷,靈堂內(nèi)的尸體忽然破棺而出恕沫,到底是詐尸還是另有隱情,我是刑警寧澤纱意,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布婶溯,位于F島的核電站,受9級(jí)特大地震影響偷霉,放射性物質(zhì)發(fā)生泄漏迄委。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一类少、第九天 我趴在偏房一處隱蔽的房頂上張望叙身。 院中可真熱鬧,春花似錦硫狞、人聲如沸信轿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)虏两。三九已至愧旦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間定罢,已是汗流浹背笤虫。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留祖凫,地道東北人琼蚯。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像惠况,于是被迫代替她去往敵國(guó)和親遭庶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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

  • 一稠屠、 序列化和反序列化概念 Serialization(序列化)是一種將對(duì)象以一連串的字節(jié)描述的過程峦睡;反序列化de...
    步積閱讀 1,443評(píng)論 0 10
  • 如果你只知道實(shí)現(xiàn) Serializable 接口的對(duì)象,可以序列化為本地文件权埠。那你最好再閱讀該篇文章榨了,文章對(duì)序列化...
    jiangmo閱讀 479評(píng)論 0 2
  • JAVA序列化機(jī)制的深入研究 對(duì)象序列化的最主要的用處就是在傳遞,和保存對(duì)象(object)的時(shí)候,保證對(duì)象的完整...
    時(shí)待吾閱讀 10,868評(píng)論 0 24
  • 概念 序列化是將對(duì)象狀態(tài)轉(zhuǎn)換為可保持或傳輸?shù)母袷降倪^程。與序列化相對(duì)的是反序列化攘蔽,它將流轉(zhuǎn)換為對(duì)象龙屉。 這兩個(gè)過程結(jié)...
    Moonsmile閱讀 399評(píng)論 0 0
  • 不論是沙盤游戲中的哪一種沙具都具有他自己的象征意義。 個(gè)體沙盤游戲中满俗,咨詢師的任務(wù)與成長(zhǎng)沙盤游戲咨詢師應(yīng)具備基本素...
    我看這個(gè)昵稱有人用嗎閱讀 155評(píng)論 0 0