国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

談談J2SE中的序列化之接受默認序列化

2019-11-18 15:37:36
字體:
來源:轉載
供稿:網(wǎng)友

  首先要了解java默認的序列化行為,java將一切關于對象的信息都保存了下了,也就是說,有些時候那些不需要保存的也被保存了下來。一般情況下,我們僅僅需要保存邏輯數(shù)據(jù)就可以了。不需要保存的數(shù)據(jù)我們可以用要害字transient標出。

  以下是一個例子:

import java.io.*;

public class Serial implements Serializable {
 int company_id;
 String company_addr;

 transient boolean company_flag;
}
  則company_flag字段將不會參與序列化與反序列化,但同時你也增加了為他初始值的責任。這也是序列化經(jīng)常導致的問題之一。因為序列化相當于一個只接受數(shù)據(jù)流的public構造函數(shù),這種對象構造方法是語言之外的。但他仍然是一種形式上的構造函數(shù)。如若你的類不能夠通過其他方面來保證初始化,則你需要額外的提供readObject方法,首先正常的反序列化,然后對transient標示的字段進行初始化。

  在不適合的時候,使用java默認的序列化行為可能會帶來速度上的影響,最糟糕的情況是,可能導致溢出。在某些數(shù)據(jù)結構的實現(xiàn)中,經(jīng)常會充斥著各種的循環(huán)引用,而java的默認序列化行為,并不了解你的對象結構,其結果就是java試圖通過一種昂貴的“圖遍歷”來保存對象狀態(tài)。可想而知,不但慢而且可能溢出。這時候你就要提供自己的readObject,來代替默認的行為。

  兼容性問題

  兼容性歷來是復雜而麻煩的問題。

  不要兼容性:

  首先來看看假如我們的目的是不要兼容性,應該注重哪些。不要兼容性的場合很多,比如war3每當版本升級就不能夠讀取以前的replays。

  兼容也就是版本控制,java通過一個名為UID(stream unique identifier)來控制,這個UID是隱式的,它通過類名,方法名等諸多因素經(jīng)過計算而得,理論上是一一映射的關系,也就是唯一的。假如UID不一樣的話,就無法實現(xiàn)反序列化了,并且將會得到InvalidClassException。

  當我們要人為的產(chǎn)生一個新的版本(實現(xiàn)并沒有改動),而拋棄以前的版本的話,可以通過顯式的聲名UID來實現(xiàn):

PRivate static final long serialVersionUID=????;
  你可以編造一個版本號,但注重不要重復。這樣在反序列化的時候老版本將得到InvalidClassException,我們可以在老版本的地方捕捉這個異常,并提示用戶升級的新的版本。

  當改動不大時,保持兼容性(向下兼容性的一個特例):

  有時候你的類增加了一些無關緊要的非私有方法,而邏輯字段并不改變的時候,你當然希望老版本和新版本保持兼容性,方法同樣是通過顯式的聲名UID來實現(xiàn)。下面我們驗證一下。

  老版本:

import java.io.*;

public class Serial implements Serializable {

 int company_id;
 String company_addr;

 public Serial1(int company_id, String company_addr) {
  this.company_id = company_id;
  this.company_addr = company_addr;
 }

 public String toString() {
  return "DATA: "+company_id+" "+
  company_addr;
 }
}
  新版本

import java.io.*;

public class Serial implements Serializable {

 int company_id;
 String company_addr;
 public Serial1(int company_id, String company_addr) {
  this.company_id = company_id;
  this.company_addr = company_addr;
 }

 public String toString() {
  return "DATA: "+company_id+" "+ company_addr;
 }
 public void todo(){}//無關緊要的方法
}
  首先將老版本序列化,然后用新版本讀出,發(fā)生錯誤:

java.io.InvalidClassException: Serial.Serial1; local class incompatible: stream classdesc serialVersionUID = 762508508425139227, local class serialVersionUID = 1187169935661445676
  接下來我們加入顯式的聲名UID:

private static final long serialVersionUID=762508508425139227l;
  再次運行,順利地產(chǎn)生新對象

DATA: 1001 com1

  如何保持向上兼容性:

  向上兼容性是指老的版本能夠讀取新的版本序列化的數(shù)據(jù)流。經(jīng)常出現(xiàn)在我們的服務器的數(shù)據(jù)更新了,仍然希望老的客戶端能夠支持反序列化新的數(shù)據(jù)流,直到其更新到新的版本。可以說,這是半自動的事情。

  跟一般的講,因為在java中serialVersionUID是唯一控制著能否反序列化成功的標志,只要這個值不一樣,就無法反序列化成功。但只要這個值相同,無論如何都將反序列化,在這個過程中,對于向上兼容性,新數(shù)據(jù)流中的多余的內容將會被忽略;對于向下兼容性而言,舊的數(shù)據(jù)流中所包含的所有內容都將會被恢復,新版本的類中沒有涉及到的部分將保持默認值。利用這一特性,可以說,只要我們認為的保持serialVersionUID不變,向上兼容性是自動實現(xiàn)的。

  當然,一但我們將新版本中的老的內容拿掉,情況就不同了,即使UID保持不變,會引發(fā)異常。正是因為這一點,我們要牢記一個類一旦實現(xiàn)了序列化又要保持向上下兼容性,就不可以隨隨便便的修改了!!!

  測試也證實了這一點,有愛好的讀者可以自己試一試。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 铅山县| 屏南县| 锦州市| 大理市| 通海县| 阿拉尔市| 苗栗县| 涟源市| 昌平区| 厦门市| 曲水县| 惠安县| 六枝特区| 东乌珠穆沁旗| 修水县| 东山县| 周口市| 凌云县| 甘洛县| 临邑县| 兴安盟| 楚雄市| 台北市| 乌恰县| 大渡口区| 舞钢市| 西乌珠穆沁旗| 吉林省| 华坪县| 四平市| 秭归县| 贡觉县| 湖州市| 东丰县| 宜章县| 上高县| 页游| 三亚市| 北辰区| 慈溪市| 凤翔县|