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

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

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

    隨筆 - 59  文章 - 70  trackbacks - 0
    <2009年1月>
    28293031123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(5)

    隨筆分類

    隨筆檔案

    搜索

    •  

    積分與排名

    • 積分 - 173476
    • 排名 - 340

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    轉(zhuǎn)自:http://tbase.itpub.net/post/4931/42269
    一些java類中為什么需要重載 serialVersionUID 屬性。

    在Java中,軟件的兼容性是一個(gè)大問題,尤其在使用到對(duì)象串行性的時(shí)候,那么在某一個(gè)對(duì)象已經(jīng)被串行化了,可是這個(gè)對(duì)象又被修改后重新部署了,那么在這種情況下, 用老軟件來讀取新文件格式雖然不是什么難事,但是有可能丟失一些信息。

    serialVersionUID來解決這些問題,新增的serialVersionUID必須定義成下面這種形式:static final long serialVersionUID=-2805284943658356093L;。其中數(shù)字后面加上的L表示這是一個(gè)long值。 通過這種方式 來解決不同的版本之間的串行話問題。


    提綱:

    ━━━━━━━━

    一、概述

    二、Java串行化

    三、引入版本編號(hào)

    四、結(jié)束語

    ━━━━━━━━

    一、概述

    一個(gè)程序正式發(fā)行出去之后,如果要增加一些新的功能,往往意味著同時(shí)要修改用戶保存數(shù)據(jù)的方式,也就是必須更改程序保存文件的格式——通常是增加保存到文件的數(shù)據(jù)。有些時(shí)候,文件格式必須作徹底的改動(dòng),以配合實(shí)現(xiàn)程序的新功能。從這個(gè)意義上看,文件格式的發(fā)展/變化總是和程序的功能改進(jìn)相呼應(yīng)。

    但是,大多數(shù)情況下,把原有的數(shù)據(jù)格式一丟了事是行不通的。動(dòng)物王國(guó)中,不能適應(yīng)環(huán)境意味著死亡;軟件領(lǐng)域也相似,新軟件是否支持原有的數(shù)據(jù)格式很大程度上決定了用戶是否升級(jí)。

    不管軟件新增/改進(jìn)了多少功能,不管新的文件格式是多么完美,如果新軟件不能利用原來的文件格式,用戶一般不太會(huì)認(rèn)可新軟件。解決該問題的辦法包括:

    ●保留老代碼來讀取老文件。采用這種方案一般需要額外編寫一些代碼,把老文件轉(zhuǎn)換成新的格式(一般地,最簡(jiǎn)單的辦法是先把老文件的數(shù)據(jù)轉(zhuǎn)換成新的內(nèi)部對(duì)象,然后利用現(xiàn)有的寫入新版文件格式的對(duì)象)。這種辦法的好處是既保留了原有的代碼,又使它與新的文件格式兼容。但是,這種辦法有時(shí)可能導(dǎo)致丟失部分?jǐn)?shù)據(jù),不過總要比丟失全部數(shù)據(jù)好。

    ●使新版軟件能夠讀/寫老文件格式。這種辦法工作量較大,因?yàn)槌绦虻男掳姹疽话銜?huì)增加一些原來沒有的功能,老的數(shù)據(jù)格式中通常缺乏新功能必需的某些數(shù)據(jù)。

    當(dāng)新版軟件對(duì)原來執(zhí)行任務(wù)的方式作了根本性的變動(dòng)時(shí),丟失數(shù)據(jù)決非難得一見的偶然事件。如果新版軟件采用和原來不同的方式達(dá)到同樣的效果,原來的功能可能不再有保留的必要。例如,如果一個(gè)程序原來用Swing做用戶界面,現(xiàn)在把它改成了Web(瀏覽器)用戶界面,原來的許多用戶界面設(shè)置就不再有效。

    又如,如果有一個(gè)郵件程序,原來用的是以文件夾為基礎(chǔ)的索引,現(xiàn)在把它改成了以單詞為基礎(chǔ)的索引系統(tǒng),在升級(jí)索引文件格式的過程中就有可能丟失許多信息;如果原來的索引文件保存了許多用戶配置選項(xiàng)和優(yōu)化措施,在新的索引系統(tǒng)中這些數(shù)據(jù)可能無法利用。

    這類問題沒有絕對(duì)完美的解決辦法,但是我們可以采取一些措施,使得升級(jí)文件格式帶來的負(fù)面影響盡可能小。Java串行化(Serialization)有著簡(jiǎn)單易用的特點(diǎn),日益成為一種保存文件的重要手段,有鑒于此,下面我們就來看看在軟件版本變更過程中,通過Java串行化保存的文件如何保持兼容性。

    二、Java串行化

    Java串行化有許多優(yōu)點(diǎn):

    ●容易使用。

    ●如果一個(gè)對(duì)象連接到其他對(duì)象,串行化機(jī)制會(huì)保存所有相關(guān)的對(duì)象。

    ●如果某個(gè)對(duì)象出現(xiàn)多次,串行化機(jī)制只保存一次。這一點(diǎn)極為重要,它不僅減小了文件空間,而且即使代碼寫得不是很老練,也不必?fù)?dān)心會(huì)出現(xiàn)無限循環(huán)(一個(gè)不老練的例子是,用遞歸的方式保存各個(gè)對(duì)象,卻又未能有效審計(jì)哪些對(duì)象已經(jīng)保存,這時(shí)就有可能陷入永無終止的循環(huán))。

    遺憾的是,Java串行化機(jī)制定義的文件格式似乎很脆弱,只要稍微改動(dòng)一下類的定義,原來保存的對(duì)象就可能無法讀取。例如,下面是一個(gè)簡(jiǎn)單的類定義:

    public class Save implements Serializable
    {
    String name;

    public void save() throws IOException
    {
    FileOutputStream f = new FileOutputStream("foo");
    ObjectOutputStream oos = new ObjectOutputStream(f);
    oos.writeObject(this);
    oos.close();
    }
    }



    如果在這個(gè)類定義中增加一個(gè)域,例如final int val = 7;,再來讀取原來保存的對(duì)象,就會(huì)出現(xiàn)下面的異常:

    java.io.InvalidClassException:
    Save; local class incompatible:
    stream classdesc serialVersionUID = -2805284943658356093,
    local class serialVersionUID = 3419534311899376629



    上例異常信息中的數(shù)字串表示類定義里各種屬性的編碼值:

    ●類的名字(Save)。

    ●域的名字(name)。

    ●方法的名字(Save)。

    ●已實(shí)現(xiàn)的接口(Serializable)。

    改動(dòng)上述任意一項(xiàng)內(nèi)容(無論是增加或刪除),都會(huì)引起編碼值變化,從而引起類似的異常警報(bào)。這個(gè)數(shù)字序列稱為“串行化版本統(tǒng)一標(biāo)識(shí)符”(serial version universal identifier),簡(jiǎn)稱UID。解決這個(gè)問題的辦法是在類里面新增一個(gè)域serialVersionUID,強(qiáng)制類仍舊使用原來的UID。新增的域必須是:

    ●static:該域定義的屬性作用于整個(gè)類,而非特定的對(duì)象。

    ●final:保證代碼運(yùn)行期間該域不會(huì)被修改。

    ●long:它是一個(gè)64位的數(shù)值。

    也就是說,新增的serialVersionUID必須定義成下面這種形式:static final long serialVersionUID=-2805284943658356093L;。其中數(shù)字后面加上的L表示這是一個(gè)long值。

    當(dāng)然,改動(dòng)之后的類不一定能夠和原來的對(duì)象兼容。例如,如果把一個(gè)域的定義從String改成了int,執(zhí)行逆-串行化操作時(shí)系統(tǒng)就不知道如何處理該值,顯示出錯(cuò)誤信息:java.io.InvalidClassException: Save; incompatible types for field name。

    Java串行化規(guī)范(http://java.sun.com/j2se/1.4.1/docs/guide/

    serialization/spec/serialTOC.doc.html)提供了有關(guān)兼容的改動(dòng)(http://java.sun.com/j2se/1.4.1/docs/

    guide/serialization/spec/version.doc7.html)和不兼容改動(dòng)(http://java.sun.com/j2se/1.4.1/docs/guide/

    serialization/spec/version.doc8.html)的清單,這些清單指出了對(duì)類作了哪些改動(dòng)之后仍可能讀取原來串行化的數(shù)據(jù)。具體細(xì)節(jié)比較復(fù)雜,但了解其主要機(jī)制還是很容易的:





    簡(jiǎn)而言之,如果文件中確實(shí)保存了所有必需的數(shù)據(jù),那么仍有可能讀取該文件,當(dāng)然前提是必須處理好串行化的UID。

    三、引入版本編號(hào)

    許多程序都在無意之中作出了這樣的假設(shè):這種文件格式是我要用到的最后一種格式,以后不再需要制定新的格式,現(xiàn)在要做的是處理好在此之前的各種格式。這種程序會(huì)試圖讀取格式版本更高的文件,操作進(jìn)行到一半才發(fā)現(xiàn)某些不能識(shí)別的數(shù)據(jù),然后就是突然崩潰。如果文件包含了大量的元數(shù)據(jù)(描述文件本身的數(shù)據(jù)),處理起來就要容易得多。

    在Java中,每一個(gè)域都由其名稱顯式標(biāo)明,只要文件的改動(dòng)不是很大(只添加了域,沒有被刪除或作重大更改的域),可以想象,用老軟件來讀取新文件格式不是什么難事,雖然有可能丟失一些信息,但可以搞清楚文件的基本情況。

    文件格式隨著程序功能的改變而改變。理想情況下,程序應(yīng)當(dāng)做到既向后兼容(新的版本能夠按照老版本的格式讀取,甚至可能允許更新),同時(shí)做到向前兼容(較老的軟件能夠識(shí)別和處理新版的文件格式)。

    通常,文件的版本無法從表面上一眼看出。大多數(shù)程序不會(huì)因?yàn)槲募陌姹静煌奈募U(kuò)展名,而且目前尚無統(tǒng)一的標(biāo)記文件版本的辦法。因此,有關(guān)文件格式的版本聲明只能在文件本身之內(nèi)進(jìn)行。如果你現(xiàn)在使用的文件格式還不包含版本聲明,最好在下次把文件升級(jí)成一個(gè)不兼容的版本時(shí)馬上加入版本標(biāo)記,或者尋求一種在當(dāng)前文件格式中加入版本標(biāo)記但不會(huì)帶來負(fù)面影響的辦法。

    版本信息一般在文件的開頭聲明,這是因?yàn)槌绦虮仨氃谔幚砦募笆紫葯z查文件的版本,除非確定了文件的版本,否則不必讀取文件的其余部分。

    按照慣例,文件版本編號(hào)包含兩個(gè)部分:主版本編號(hào)和次版本編號(hào)。一個(gè)特定版本的程序應(yīng)當(dāng)有最適合它處理的主-次版本號(hào);主版本號(hào)變化意味著文件格式的重大變化,要繼續(xù)使用已經(jīng)非常困難,必須作出重大修改才能升級(jí)到新的版本。

    文件的主次版本號(hào)之前往往還可以加入另一項(xiàng)內(nèi)容,稱為“魔術(shù)數(shù)字”,它的作用就是保證程序處理的文件類型不會(huì)有誤(因?yàn)槲募U(kuò)展名有可能不能唯一地標(biāo)明文件類型)。例如,Java的類文件總是以下列字節(jié)內(nèi)容開頭(十六進(jìn)制):CA FE BA BE。目前還沒有這類數(shù)字的統(tǒng)一注冊(cè)機(jī)構(gòu),不過UNIX在/etc/magic下提供了一個(gè)清單(但并不完整)。魔術(shù)數(shù)字一般有四個(gè)字節(jié),取值范圍很大,所以一般不必?fù)?dān)心會(huì)出現(xiàn)取值沖突的情形。

    在編寫和維護(hù)必須讀/寫文件的代碼時(shí),注意代碼的向前/向后兼容性是非常必要的。在處理文件的代碼中首先讀取文件版本,然后根據(jù)版本號(hào)將文件剩余內(nèi)容傳遞給適當(dāng)?shù)奶幚矸椒ǎ蝗绻募陌姹咎希巡辉僦С郑绦驊?yīng)當(dāng)給出明確的提示。

    四、結(jié)束語

    文件格式設(shè)計(jì)是一個(gè)極其重要的話題,但本文還有許多細(xì)節(jié)問題尚未涉及。例如,對(duì)于大型文件,我們需要隨機(jī)訪問,而不是從前向后依次讀取文件內(nèi)容的順序訪問,這樣就不必為了訪問文件最后幾個(gè)字節(jié)而讀取整個(gè)文件。無論是XML還是Java串行化對(duì)這類隨機(jī)訪問的支持都不是很理想,而且這類文件格式的發(fā)展變化比普通文件更難管理,因?yàn)樗麄円蕾囉谧止?jié)級(jí)的訪問,稍微改動(dòng)一下文件格式就可能導(dǎo)致不兼容。

    如果要讓文件具有ACID特性——Atomicity、Consistency、Isolation和Durability,即原子性、一致性、隔離性、持久性,問題更加復(fù)雜。ACID與事務(wù)的概念密切相關(guān),支持多用戶同時(shí)訪問一個(gè)文件。對(duì)于這類文件,可以考慮采用某種小型的數(shù)據(jù)庫系統(tǒng),例如Birdstep或Sleepycat。不過這已經(jīng)進(jìn)入了文件格式管理的另一個(gè)領(lǐng)域,既涉及到數(shù)據(jù)庫管理軟件的版本,也涉及到數(shù)據(jù)模式設(shè)計(jì)的版本。

    撇開這些復(fù)雜的問題不談,在實(shí)踐中,很多時(shí)候我們只需簡(jiǎn)單的文件來保存數(shù)據(jù),而且不會(huì)出現(xiàn)多用戶并發(fā)訪問,可以一次性地處理整個(gè)文件(或者至少適合使用順序訪問方式)。對(duì)于這些情形,最好在設(shè)計(jì)文件格式時(shí)就考慮版本問題,在日后的運(yùn)行、維護(hù)中一定會(huì)帶來不少方便。
    posted on 2009-01-21 11:18 JasonChou 閱讀(2390) 評(píng)論(0)  編輯  收藏 所屬分類: j2se
    主站蜘蛛池模板: 最近免费中文在线视频| 黄色免费在线网址| 久久精品国产亚洲av日韩| 亚洲大尺度无码无码专区| 亚洲色图黄色小说| 精品亚洲成A人在线观看青青 | 亚洲综合校园春色| 看一级毛片免费观看视频| 无码人妻丰满熟妇区免费| 青青青国产在线观看免费网站| 国产成人免费福利网站| 亚洲精品成人片在线播放| 亚洲一区二区三区久久| 三根一起会坏掉的好痛免费三级全黄的视频在线观看 | 亚洲日本国产综合高清| 爽爽爽爽爽爽爽成人免费观看 | 免费观看国产精品| 亚洲av一本岛在线播放| 妞干网免费观看视频| 亚洲短视频男人的影院| 特级aa**毛片免费观看| 国产亚洲色视频在线| 亚洲性线免费观看视频成熟| 女人18特级一级毛片免费视频| 日韩免费高清一级毛片| 国产一级婬片A视频免费观看| 亚洲国产精品无码久久久蜜芽 | 最近免费中文字幕大全免费版视频| 亚洲国产精品丝袜在线观看| 337p日本欧洲亚洲大胆色噜噜| 国产精品久久久久久久久久免费| 亚洲AV无码专区国产乱码电影 | 国产精品日本亚洲777| 亚洲男人的天堂www| 高清免费久久午夜精品 | 日本特黄特黄刺激大片免费| 亚洲伊人久久大香线蕉影院| 最近2018中文字幕免费视频| 亚洲中文字幕无码爆乳app| 8x网站免费入口在线观看| 亚洲人成网站色7799|