Serializable
Serializable是一個空接口攒菠,沒有什么具體內(nèi)容哨免,它的目的只是簡單的標識一個類的對象可以被序列化茎活。
什么情況下需要序列化:
- 當你想把的內(nèi)存中的對象寫入到硬盤的時候;
- 當你想用套接字在網(wǎng)絡(luò)上傳送對象的時候琢唾;
- 當你想通過RMI傳輸對象的時候载荔,比如說你的內(nèi)存不夠用了,那計算機就要將內(nèi)存里面的一部分對象暫時的保存到硬盤中采桃,等到要用的時候再讀入到內(nèi)存中懒熙,硬盤的那部分存儲空間就是所謂的虛擬內(nèi)存。在比如過你要將某個特定的對象保存到文件中普办,我隔幾天在把它拿出來用工扎,那么這時候就要實現(xiàn)Serializable接口;
serialVersionUID
提到 serialVersionUID 就不得不提到 ObjectOutputStream 與 ObjectInputStream 衔蹲,因為僅當使用這兩個流對象時serialVersionUID才會起作用肢娘。
簡單來說,Java的序列化機制是通過類的serversionUID來驗證版本一致性的。在反序列化時橱健,JVM會將傳來的字節(jié)流中的serialVersionUID與本地相應(yīng)實體類的serialVersionUID進行比較而钞,如果相同就認為是一致的,可以進行反序列化拘荡,否則就會出現(xiàn)序列化版本不一致的異常臼节,即是InvalidCastException。
serialVersionUID有三種常見的生成方案:
- 根據(jù)類名珊皿、接口名网缝、成員方法及屬性等來生成一個64位的哈希字段,比如:
private static final long serialVersionUID = xxxL亮隙; - 默認的1L途凫,比如:private static final long serialVersionUID = 1L;
- 完全隨機生成溢吻;
關(guān)于三種方案的解析:
第一種方案:沒有手動聲明serialVersionUID時java的默認策略维费,serialVersionUID的默認值完全依賴于Java編譯器的實現(xiàn),對于同一個類促王,用不同的Java編譯器編譯犀盟,有可能會導(dǎo)致不同的serialVersionUID。
通常如果Class文件(類名蝇狼、方法名等)沒有發(fā)生變化(增加空格阅畴、換行、增加注釋等等)迅耘,就算編譯多次贱枣,servialVersionUID也不會變化的。第二種方案:當場景沒有特殊要求時可以使用這種方案颤专。
第三種方案:通常是為了保證序列化安全纽哥,假設(shè)serialVersionUID很容易被猜到,那么其他人就很容易反序列化該對象得到對象中保存的信息栖秕。所以當使用場景涉及到安全問題時春塌,我們盡量保證serialVersionUID隨機。
如果不想讓之前的版本參與當前版本的反序列化時可以通過改動serialVersionUID版本來實現(xiàn)簇捍。從而避免不同版本間的反序列化混亂只壳。(限于手動聲明serialVersionUID的方案)