簡單來說,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,可避開不兼容性問題。