<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-1  評論-9  文章-7  trackbacks-0

    1.概述

         要實現(xiàn)序列化,則必須實現(xiàn)serializable或Externalizable接口。后者繼承自前者,兩者的區(qū)別:實現(xiàn)前者的類可以采用默認(rèn)的序列化方式。而實現(xiàn)后者的類則完全由自身來控制序列化的行為。
         在序列化和反序列化過程中需要特殊處理的類必須使用下列準(zhǔn)確簽名來實現(xiàn)特殊方法:

    private void writeObject java.io.ObjectOutputStream out) throws IOException   
    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;  

         writeObject 方法負(fù)責(zé)寫入特定類的對象的狀態(tài),以便相應(yīng)的 readObject 方法可以還原它。通過調(diào)用 out.defaultWriteObject 可以調(diào)用保存 Object 的字段的默認(rèn)機(jī)制。該方法本身不需要涉及屬于其超類或子類的狀態(tài)。狀態(tài)是通過使用 writeObject 方法或使用 DataOutput 支持的用于基本數(shù)據(jù)類型的方法將各個字段寫入 ObjectOutputStream 來保存的。
          readObject 方法負(fù)責(zé)從流中讀取并還原類字段。它可以調(diào)用 in.defaultReadObject 來調(diào)用默認(rèn)機(jī)制,以還原對象的非靜態(tài)和非瞬態(tài)字段。defaultReadObject 方法使用流中的信息來分配流中通過當(dāng)前對象中相應(yīng)命名字段保存的對象的字段。這用于處理類發(fā)展后需要添加新字段的情形。該方法本身不需要涉及屬于其超類或子類的狀態(tài)。狀態(tài)是通過使用 writeObject 方法或使用 DataOutput 支持的用于基本數(shù)據(jù)類型的方法將各個字段寫入 ObjectOutputStream 來保存的。 
          假定有一個名為Customer的類,它的對象需要序列化,如果Customer類僅僅實現(xiàn)了Serializable接口的類,那么將按照以下方式序列化及反序列化Customer對象:
    • ObjectOutputStream采用默認(rèn)的序列化方式,對Customer對象的非transient的實例變量進(jìn)行序列化。
    • ObjectInputStream采用默認(rèn)的反序列化方式,對Customer對象的非transient的實例變量進(jìn)行反序列化。
       如果Customer類僅僅實現(xiàn)了Serializable接口的類,并且還定義了readObject(ObjectInputStream in)和writeObject(ObjectOutputStream out)方法,那么將按照以下方式序列化及反序化Customer對象:
    • ObjectOutputStream會調(diào)用Customer類的writeObject(ObjectOutputStream out)方法來進(jìn)行序列化。
    • ObjectInputStream會調(diào)用Customer類的readObject(ObjectInputStream in)方法來進(jìn)行反序列化。

         如果Customer類實現(xiàn)了Externalizable接口,那么Customer類必須實現(xiàn)readExternal
         (ObjectInput in)和writeExternal(ObjectOutput out)方法。在這種情況下,將按照以下方式序列化及反序列化Customer對象:

    • ObjectOutputStream會調(diào)用Customer類的writeExternal(ObjectOutput out)方法來進(jìn)行序列化。
    •  ObjectInputStream先通過Customer類的不帶參數(shù)的構(gòu)造方法創(chuàng)建一個Customer對象,然后調(diào)用它的readExternal(ObjectInput int)方法來進(jìn)行反序列化。

    2.實現(xiàn)Serializable接口

           ObjectOutputStream只能對實現(xiàn)了Serializable接口的類的對象進(jìn)行序列化。默認(rèn)情況下,ObjectOutputStream按照默認(rèn)方式序列化,這種序列化方式僅僅對對象的非transient的實例變量進(jìn)行序列化,而不會序列化對象的transient的實例變量,也不會序列化靜態(tài)變量。

          而當(dāng)ObjectInputStream按照默認(rèn)方式反序列化時,有以下特點:

    • 如果在內(nèi)在中對象所屬的類還沒有被加載,那么會先加載并初始化這個類。如果在classpath中不存在相應(yīng)的類文件,那么會拋出ClassNotFoundException。
    • 在反序列化時不會調(diào)用類的任何構(gòu)造方法。

         被transient修飾符來修飾的實例變量是不會序列化的,一般用transient來修飾以下類型的的變量:

        1) 實例變量不代表對象的固有的內(nèi)部數(shù)據(jù),僅僅代表具有一定邏輯含義的臨時數(shù)據(jù)。
        2) 實例變量表示一些比較敏感的信息,如密碼,出于安全方面的原因,不希望對其序列化。
        3) 實例變量需要按照用戶自定義的方式序列化,如經(jīng)過加密后再序列化。這這種情況下可以將其用transient修飾,然后在writeObject()方法中對其序列化。   

    2.1序列化對象圖

        參見SerializableDemo中的Customer2及Order2類之間的關(guān)系。
        當(dāng)通過ObjectOutputStream對象的writeObject(customer)方法序列化Customer2對象時,也會序列化與它關(guān)聯(lián)的Order2對象。而當(dāng)通過ObjectInputStream對象的readObject()方法反序列化Customer2對象時,實際上會對整個對象圖反序列化。
        如果對象A持有對象B的引用(注意是A持有B的引用),以及間接持有其他對象的引用,則按照默認(rèn)方式序列化對象A時,會將A以及A持有的以及間接持有的所有對象都序列化。反序列化也是如此。

       

    2.2控制序列化的行為

        如果用戶希望控制類的序列化方式,可以在可序列化類中提供以下形式的writeObject()方法和readObject()方法:

    private void writeObject java.io.ObjectOutputStream out)throws IOException   
    private void readObject java.io.ObjectInputStream in)throws IOException,ClassNotFoundException;  

        一般的做法是,在writeObject()方法中,選留骼ObjectOutputStream的defaultWriteObject()方法,使得對象輸出流先執(zhí)行默認(rèn)的序列化操作。
        反序列化時,在readObject()方法中,先調(diào)用ObjectInputStream的defaultReadObject()方法。

       

    2.3readResolve()方法在童便類中的運用


        如果一個類提供了readResolve()方法,那么在執(zhí)行反序列化操作時,先按照默認(rèn)方式或者用戶自定義的方式進(jìn)行反序列化,最后再調(diào)用readResolve()方法,該方法返回的對象為反序列化的最終結(jié)果。
        readResolve()方法應(yīng)該能夠被類本身、同一個包中的類,或者訪問,因此readResolve()方法的訪問權(quán)限可以是pirvate、默認(rèn)或protected級別。
        readResolve()方法用來重新指定反序列化得到的對象,與此對應(yīng),Java序列化規(guī)范還允許在可序列化類中定義一個writeReplace()方法,用來重新指定被序列化的對象。writeReplace()方法返回一個Object類型的對象,這個返回對象才是真正要被序列化的對象。權(quán)限也可以為以上三種之一。  

    3.實現(xiàn)Externalizalbe接口

           Externallizable接口繼承自Serializable接口,如果一個類實現(xiàn)了Externalizable接口,那么將完全由這個類控制自身的序列化行為。Externalizable接口中聲明了兩個方法:

    public void writeExternal(ObjectOutput out)throws IOException   
    public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException  

        writeExternal負(fù)責(zé)序列化操作,readExternal負(fù)責(zé)反序列化操作。在對實現(xiàn)了Externallizable接口的類的對象進(jìn)行反序列化時,會先調(diào)用類的不帶參數(shù)的構(gòu)造方法,這是有別默認(rèn)反序列化方式的(見2)。所以實現(xiàn)Externalizable接口的類必須要有不含參數(shù)的構(gòu)造方法。

     

    4.可序列化類的不同版本的序列化兼容性

        實例見SerializableDemo里的Customer5的兩個版本。將Customer1.0和SimpleServer放在server端,將Customer2.0和SimpleClient放在Client端,直接運行,將發(fā)現(xiàn)拋出錯誤,顯示不兼容,解決辦法是手動將兩個Customer的serialVersionUID設(shè)為同一個值,這樣就能兼容。但是這種辦法的能力很有限,當(dāng)一個類的不同版本的serialVersionUID相同,仍然有可能出現(xiàn)序列化不兼容的情況。因為序列化兼容性不僅取決于serialVersionUID,還取決于類的不同版本的實現(xiàn)細(xì)節(jié)和序列化細(xì)節(jié)。

    posted on 2010-03-28 16:33 Dreava 閱讀(1183) 評論(0)  編輯  收藏 所屬分類: Java基礎(chǔ)

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲AV电影天堂男人的天堂| 国产麻豆剧传媒精品国产免费 | vvvv99日韩精品亚洲| 国产91在线免费| 亚洲AV无码成人专区片在线观看| 亚洲国产成人久久精品动漫| 最新国产精品亚洲| 特级毛片A级毛片免费播放| 免费在线观看一级片| 最近最新中文字幕完整版免费高清 | 亚洲黄色免费网址| 激情小说亚洲图片| 1000部拍拍拍18免费网站| 免费人成在线观看播放国产 | 国产精品jizz在线观看免费| 亚洲人成色77777| 亚洲精品无码中文久久字幕| 久久精品中文字幕免费| 一区二区三区亚洲视频| 一级全免费视频播放| 最近免费中文字幕大全视频| 亚洲欧好州第一的日产suv| 国产精品国产免费无码专区不卡 | 亚洲国产精品久久久久秋霞影院| 亚洲伊人色一综合网| 女性自慰aⅴ片高清免费| 亚洲国产日韩在线| 午夜视频在线观看免费完整版| 国产亚洲精品仙踪林在线播放| 免费无码又爽又刺激聊天APP| 亚洲天堂中文字幕| 日韩毛片免费无码无毒视频观看| 亚洲aⅴ无码专区在线观看春色| 亚洲人成无码网WWW| 青青免费在线视频| 亚洲成AV人片在线观看无码| 成人网站免费看黄A站视频| 中文字幕亚洲不卡在线亚瑟| 免费看内射乌克兰女| 亚洲美女高清一区二区三区 | 亚洲色偷偷综合亚洲av78 |