序列化中serialVersionUID的作用

簡單來說,Java的序列化機(jī)制是通過在運(yùn)行時(shí)判斷類的serialVersionUID來驗(yàn)證版本一致性的。在進(jìn)行反序列化時(shí),JVM會把傳來的字節(jié)流中的serialVersionUID與本地相應(yīng)實(shí)體(類)的serialVersionUID進(jìn)行比較,如果相同就認(rèn)為是一致的,可以進(jìn)行反序列化,否則就會出現(xiàn)序列化版本不一致的異常。(InvalidCastException)

serialVersionUID兩種顯示的生成方式:

一個(gè)是默認(rèn)的1L,比如:private static final long serialVersionUID = 1L;

一個(gè)是根據(jù)類名、接口名、成員方法及屬性等來生成一個(gè)64位的哈希字段,比如:private static final?? long????serialVersionUID = xxxxL;



當(dāng)你一個(gè)類實(shí)現(xiàn)了Serializable接口,如果沒有顯示的定義serialVersionUID,Eclipse會提供這個(gè),提示功能告訴你去定義 。在Eclipse中點(diǎn)擊類中warning的圖標(biāo)一下,Eclipse就會




當(dāng)實(shí)現(xiàn)java.io.Serializable接口的實(shí)體(類)沒有顯式地定義一個(gè)名為serialVersionUID,類型為long的變量時(shí),Java序列化機(jī)制會根據(jù)編譯的class(它通過類名,方法名等諸多因素經(jīng)過計(jì)算而得,理論上是一一映射的關(guān)系,也就是唯一的)自動生成一個(gè)serialVersionUID作序列化版本比較用,這種情況下,如果class文件(類名,方法明等)沒有發(fā)生變化(增加空格,換行,增加注釋,等等),就算再編譯多次,serialVersionUID也不會變化的.

結(jié)論不寫就是自動生成的64位的哈希字段。


如果我們不希望通過編譯來強(qiáng)制劃分軟件版本,即實(shí)現(xiàn)序列化接口的實(shí)體能夠兼容先前版本,未作更改的類,就需要顯式地定義一個(gè)名為serialVersionUID,類型為long的變量,不修改這個(gè)變量值的序列化實(shí)體都可以相互進(jìn)行串行化和反串行化

結(jié)論常通過書寫固定的serialVersionUID來保證可以進(jìn)行序列化與反序列化

串行化和并行化

?????串行化也叫做序列化,就是把存在于內(nèi)存的對象數(shù)據(jù)轉(zhuǎn)化成可以保存成硬盤文件的形式去存儲;

并行化也叫反序列化,就是把序列化后的硬盤文件加載到內(nèi)存,重新變成對象數(shù)據(jù).也就是把內(nèi)存中對象數(shù)據(jù)變成硬盤文件.


問題一:假設(shè)有A端和B端,如果2處的serialVersionUID不一致,會產(chǎn)生什么錯(cuò)誤呢?

問題二:假設(shè)2處serialVersionUID一致,如果A端增加一個(gè)字段,B端不變,會是什么情況呢?

問題三:假設(shè)2處serialVersionUID一致,如果B段增加一個(gè)字段,A端不變,會是什么情況呢?

問題四:假設(shè)2處serialVersionUID一致,如果A端減少一個(gè)字段,B端不變,會是什么情況呢?

問題五:假設(shè)2處serialVersionUID一致,如果B端減少一個(gè)字段,A端不變,會是什么情況呢?


問題一:假設(shè)有A端和B端,如果2處的serialVersionUID不一致,會產(chǎn)生什么錯(cuò)誤呢?

答案如下:

1)先執(zhí)行測試類SerialTest,然后修改serialVersion值(或注釋掉serialVersion并編譯),再執(zhí)行測試類DeserialTest,報(bào)錯(cuò):


2)A端和B端都沒顯示的寫serialVersionUID,實(shí)體類沒有改動(如果class文件(類名,方法明等)沒有發(fā)生變化(增加空格,換行,增加注釋,等等),).序列化,反序列化正常.



3)A端沒顯示的寫serialVersionUID,實(shí)體類沒有改動(如果class文件(類名,方法明等)沒有發(fā)生變化(增加空格,換行,增加注釋,等等),) 先執(zhí)行測試類SerialTest,然后修改serialVersion值(或注釋掉serialVersion并編譯),再執(zhí)行測試類DeserialTest,報(bào)錯(cuò):

結(jié)論不寫就是自動生成的64位的哈希字段并且二者serialVersionUID相同


問題二:假設(shè)2處serialVersionUID一致,如果A端增加一個(gè)字段,B端不變,會是什么情況呢?

答案二: 序列化,反序列化正常,A端增加的字段丟失(被B端忽略).

問題五:假設(shè)2處serialVersionUID一致,如果B端減少一個(gè)字段,A端不變,會是什么情況呢?

答案:與問題二類似,序列化,反序列化正常,B端字段少于A端,A端多的字段值丟失(被B端忽略).

A端


結(jié)果


B端

結(jié)果

問題三:假設(shè)2處serialVersionUID一致,如果B段增加一個(gè)字段,A端不變,會是什么情況呢?

問題四:假設(shè)2處serialVersionUID一致,如果A端減少一個(gè)字段,B端不變,會是什么情況呢?(與問題三類似,四答案:序列化,反序列化正常,B端字段多余A端,B端多出的字段被賦予對應(yīng)類型的默認(rèn)值)

答案三: 序列化,反序列化正常,B端新增加的int字段被賦予了默認(rèn)值0.

A端


結(jié)果

B端

說明序列化,反序列化正常,B端新增加的int字段被賦予了默認(rèn)值0.


上面的情況對增加/減少 字段/方法 都適用.

但當(dāng)serialVersionUID相同時(shí),它就會將不一樣的field以type的預(yù)設(shè)值Deserialize,可避開不兼容性問題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • JAVA序列化機(jī)制的深入研究 對象序列化的最主要的用處就是在傳遞,和保存對象(object)的時(shí)候,保證對象的完整...
    時(shí)待吾閱讀 11,201評論 0 24
  • 專業(yè)考題類型管理運(yùn)行工作負(fù)責(zé)人一般作業(yè)考題內(nèi)容選項(xiàng)A選項(xiàng)B選項(xiàng)C選項(xiàng)D選項(xiàng)E選項(xiàng)F正確答案 變電單選GYSZ本規(guī)程...
    小白兔去釣魚閱讀 10,587評論 0 13
  • 如果你只知道實(shí)現(xiàn) Serializable 接口的對象,可以序列化為本地文件。那你最好再閱讀該篇文章,文章對序列化...
    jiangmo閱讀 563評論 0 2
  • 早七點(diǎn),享受陽光早餐,品讀營養(yǎng)說說。 書接上文。 城市之中,迷茫是常有的事兒。記得在2008年,從現(xiàn)代、大氣的商務(wù)...
    仲虺閱讀 258評論 1 4
  • 剛來到上海沒有多久的時(shí)候,也沒找到什么好工作,實(shí)在是窮,身上的債務(wù)還一大堆,就在郊外這邊租了一間小房子。 雖然離市...
    貓笑Y閱讀 713評論 0 1

友情鏈接更多精彩內(nèi)容