一、采用Serializable方式進(jìn)行對象的序列化和反序列化株汉,反序列化成功后得到的對象和序列化時的對象內(nèi)容完全一樣筐乳,但是兩者并不是同一個對象。
二乔妈、serialVersionUID是用來輔助序列化和反序列化過程的蝙云,原則上序列化化后的數(shù)據(jù)中的serialVersionUID只有和當(dāng)前類的serialVersionUID相同才能夠正常地被反序列化。
????serialVersionUID的詳細(xì)工作機制是這樣的:序列化的時候系統(tǒng)會把當(dāng)前類的serialVersionUID寫入序列化的文件中(也可能是其他中介)路召,當(dāng)反序列化的時候系統(tǒng)會去檢測文件中的serialVersionUID勃刨,看它是否和當(dāng)前類的serialVersionUID一致,如果一致就說明序列化的類的版本和當(dāng)前類的版本是相同的股淡,這個時候可以反序列化成功身隐;否者就說明當(dāng)前類和序列化的類相比發(fā)生了某些變換,比如成員變量的數(shù)量唯灵、類型可能發(fā)生了改變贾铝,這個時候是無法正常反序列化的。
三、一般來說垢揩,我們應(yīng)該手動指定serialVersionUID的值玖绿,比如1L,也可以讓Eclipse根據(jù)當(dāng)前類的結(jié)構(gòu)自動去生成它的hash值叁巨,這樣序列化和反序列化時兩者的serialVersionUID是相同的斑匪,因此可以正常進(jìn)行反序列化。如果不動手指定serialVersionUID的值俘种,反序列化時秤标,當(dāng)前類有所改變绝淡,比如增加或者刪除了某些成員變量宙刘,那么系統(tǒng)就會重新計算當(dāng)前類的hash值并把它賦值給serialVersionUID,這個時候當(dāng)前類的serialVersionUID就和序列化的數(shù)據(jù)中的serialVersionUID不一致牢酵,于是反序列化失敗悬包,程序就會出現(xiàn)crash。
????所以馍乙,手動指定serialVersionUID后就可以在很大程度上避免反序列化過程的失敗布近。比如當(dāng)版本升級后,我們可能刪除了某個成員變量也可能怎講了一些新的成員變量丝格,這個時候我們的反序列化過程仍能夠成功撑瞧,程序仍然能夠最大限度地恢復(fù)數(shù)據(jù),相反显蝌,如果不指定serialVersionUID的話预伺,程序會掛掉。
????當(dāng)然曼尊,如果類結(jié)構(gòu)發(fā)生了非常規(guī)性改變酬诀,比如修改了類名,修改了成員變量的烈性骆撇,這個時候盡管serilaVersionUID驗證通過瞒御,但是反序列化過程還是會失敗,因為類結(jié)構(gòu)有了毀滅性的改變神郊,根本無法從老版本的數(shù)據(jù)中還原一個新的類結(jié)構(gòu)的對象肴裙。
四、需要注意以下兩點
????首先靜態(tài)成員變量屬于類不屬于對象涌乳,所以不會參與序列化過程蜻懦;其次,用transient關(guān)鍵字標(biāo)記的成員變量不參與序列化過程爷怀。
????另外阻肩,系統(tǒng)的默認(rèn)序列化過程也是可以改變的,通過實現(xiàn)writeObject(ObjectOutputStream out)和readObject(ObjectInputStream in)兩個方法即可重寫系統(tǒng)默認(rèn)的序列化和反序列化過程。
摘自《Android開發(fā)藝術(shù)探索》