- Java核心技術(shù)·卷Ⅱ:高級(jí)特性(原書(shū)第10版)
- (美)凱S.霍斯特曼
- 1172字
- 2020-10-30 18:10:42
2.4.5 版本管理
如果使用序列化來(lái)保存對(duì)象,就需要考慮在程序演化時(shí)會(huì)有什么問(wèn)題。例如,1.1版本可以讀入舊文件嗎?仍舊使用1.0版本的用戶可以讀入新版本產(chǎn)生的文件嗎?顯然,如果對(duì)象文件可以處理類的演化問(wèn)題,那它正是我們想要的。
乍一看,這好像是不可能的。無(wú)論類的定義產(chǎn)生了什么樣的變化,它的SHA指紋也會(huì)跟著變化,而我們都知道對(duì)象輸入流將拒絕讀入具有不同指紋的對(duì)象。但是,類可以表明它對(duì)其早期版本保持兼容,要想這樣做,就必須首先獲得這個(gè)類的早期版本的指紋。我們可以使用JDK中的單機(jī)程序serialver來(lái)獲得這個(gè)數(shù)字,例如,運(yùn)行下面的命令

將會(huì)打印出

如果在運(yùn)行serialver程序時(shí)添加-show選項(xiàng),那么這個(gè)程序就會(huì)產(chǎn)生下面的圖形化對(duì)話框(參見(jiàn)圖2-7)。

圖2-7 serialver程序的圖形化版本
這個(gè)類的所有較新的版本都必須把serialVersionUID常量定義為與最初版本的指紋相同。

如果一個(gè)類具有名為serialVersionUID的靜態(tài)數(shù)據(jù)成員,它就不再需要人工地計(jì)算其指紋,而只需直接使用這個(gè)值。
一旦這個(gè)靜態(tài)數(shù)據(jù)成員被置于某個(gè)類的內(nèi)部,那么序列化系統(tǒng)就可以讀入這個(gè)類的對(duì)象的不同版本。
如果這個(gè)類只有方法產(chǎn)生了變化,那么在讀入新對(duì)象數(shù)據(jù)時(shí)是不會(huì)有任何問(wèn)題的。但是,如果數(shù)據(jù)域產(chǎn)生了變化,那么就可能會(huì)有問(wèn)題。例如,舊文件對(duì)象可能比程序中的對(duì)象具有更多或更少的數(shù)據(jù)域,或者數(shù)據(jù)域的類型可能有所不同。在這些情況中,對(duì)象輸入流將盡力將流對(duì)象轉(zhuǎn)換成這個(gè)類當(dāng)前的版本。
對(duì)象輸入流會(huì)將這個(gè)類當(dāng)前版本的數(shù)據(jù)域與被序列化的版本中的數(shù)據(jù)域進(jìn)行比較,當(dāng)然,對(duì)象流只會(huì)考慮非瞬時(shí)和非靜態(tài)的數(shù)據(jù)域。如果這兩部分?jǐn)?shù)據(jù)域之間名字匹配而類型不匹配,那么對(duì)象輸入流不會(huì)嘗試將一種類型轉(zhuǎn)換成另一種類型,因?yàn)檫@兩個(gè)對(duì)象不兼容;如果被序列化的對(duì)象具有在當(dāng)前版本中所沒(méi)有的數(shù)據(jù)域,那么對(duì)象輸入流會(huì)忽略這些額外的數(shù)據(jù);如果當(dāng)前版本具有在被序列化的對(duì)象中所沒(méi)有的數(shù)據(jù)域,那么這些新添加的域?qū)⒈辉O(shè)置成它們的默認(rèn)值(如果是對(duì)象則是null,如果是數(shù)字則為0,如果是boolean值則是false)。
下面是一個(gè)示例:假設(shè)我們已經(jīng)用雇員類的最初版本(1.0)在磁盤(pán)上保存了大量的雇員記錄,現(xiàn)在我們?cè)贓mployee類中添加了稱為department的數(shù)據(jù)域,從而將其演化到了2.0版本。圖2-8展示了將1.0版的對(duì)象讀入到使用2.0版對(duì)象的程序中的情形,可以看到department域被設(shè)置成了null。圖2-9展示了相反的情況:一個(gè)使用1.0版對(duì)象的程序讀入了2.0版的對(duì)象,可以看到額外的department域被忽略。

圖2-8 讀入具有較少數(shù)據(jù)域的對(duì)象

圖2-9 讀入具有較多數(shù)據(jù)域的對(duì)象
這種處理是安全的嗎?視情況而定。丟掉數(shù)據(jù)域看起來(lái)是無(wú)害的,因?yàn)榻邮照呷耘f擁有它知道如何處理的所有數(shù)據(jù),但是將數(shù)據(jù)域設(shè)置為null卻有可能并不那么安全。許多類都費(fèi)盡心思地在其所有的構(gòu)造器中將所有的數(shù)據(jù)域都初始化為非null的值,以使得其各個(gè)方法都不必去處理null數(shù)據(jù)。因此,這個(gè)問(wèn)題取決于類的設(shè)計(jì)者是否能夠在readObject方法中實(shí)現(xiàn)額外的代碼去訂正版本不兼容問(wèn)題,或者是否能夠確保所有的方法在處理null數(shù)據(jù)時(shí)都足夠健壯。
- 數(shù)據(jù)庫(kù)系統(tǒng)原理及MySQL應(yīng)用教程(第2版)
- FuelPHP Application Development Blueprints
- 國(guó)際大學(xué)生程序設(shè)計(jì)競(jìng)賽中山大學(xué)內(nèi)部選拔真題解(二)
- 高效微控制器C語(yǔ)言編程
- Python從菜鳥(niǎo)到高手(第2版)
- Java面向?qū)ο蟪绦蜷_(kāi)發(fā)及實(shí)戰(zhàn)
- JS全書(shū):JavaScript Web前端開(kāi)發(fā)指南
- 劍指MySQL:架構(gòu)、調(diào)優(yōu)與運(yùn)維
- MINECRAFT編程:使用Python語(yǔ)言玩轉(zhuǎn)我的世界
- Android Studio Cookbook
- Oracle實(shí)用教程
- Visual C++開(kāi)發(fā)寶典
- Solr權(quán)威指南(下卷)
- JavaWeb從入門(mén)到精通(視頻實(shí)戰(zhàn)版)
- Developing Java Applications with Spring and Spring Boot