若是某個 class implements Serializable,Eclipse 會提示生成 serialVersionUID ,多數狀況下,我都選擇是。可這個東西究竟是什麼呢?html
package com.home.demo; import java.io.Serializable; public class Item implements Serializable { private static final long serialVersionUID = 1L; private int data; public Item (int data) { this.data = data; } public int getData() { return data; } }
Eclipse 再次提醒我要有serialVersionUID 。 好吧,既然是測試,給他個值1。java
寫一個測試類,試試 serialize and deserialize Itemapi
package com.home.demo; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class UIDTest { public void save2Disk(String fileName) throws IOException{ File file = new File(fileName); FileOutputStream fos = new FileOutputStream(file); ObjectOutputStream oos = new ObjectOutputStream(fos); //set value to 101 Item serializeMe = new Item(101); oos.writeObject(serializeMe); oos.close(); System.out.println("done!"); } public void readFromDisk(String fileName) throws ClassNotFoundException, IOException{ FileInputStream fis = new FileInputStream(fileName); ObjectInputStream ois = new ObjectInputStream(fis); Item dto = (Item) ois.readObject(); System.out.println("data : " + dto.getData()); ois.close(); } /** * @param args * @throws IOException * @throws ClassNotFoundException */ public static void main(String[] args) { UIDTest test = new UIDTest(); String name = "D:/out.dat"; try{ // write file //test.save2Disk(name); //--1 test.readFromDisk(name); // --2 }catch(Exception e){ e.printStackTrace(); } } }
運行結果oracle
101
徹底正確!測試
看看D盤,有個文件out.dat. 關閉寫文件,直接讀取 out.dat ui
運行結果this
101
試試把 serialVersionUID = 2Lspa
private static final long serialVersionUID = 2L;
再運行
code
java.io.InvalidClassException: com.home.demo.Item; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
噢。。。。 出錯了!orm
根據 Java document,
Serialization is for serializing instances, not classes. Static fields (methods are irrelevant since they are part of the class definition so they aren't serialized) will be reinitialized to whatever value they are set to when the class is loaded.
根據這個說法,Item不可能知道 serialVersionUID 的值,爲何會報錯?
繼續看文檔!
好吧 serialVersionUID 屬於例外,這個值的確「get serialized」.
ObjectOutputStream writes every time the value ofserialVersionUID to the output stream.
ObjectInputStream reads it back and if the value read from the stream does not agree with the serialVersionUID value in the current version of the class, then it throws the InvalidClassException.
Moreover, if there is no serialVersionUID officially declared in the class to be serialized, compiler automatically adds it with a value generated based on the fields declared in the class.
假如你在機器A上serialize 了數據,而後送到B機器上deserialize ,須要必定的信息來幫忙肯定數據的正確性。serialVersionUID 就是用於幹這個活的。因此,Eclipse建議咱們使用的serialVersionUID ,能夠對serialization進行最簡單的檢驗和控制。
再回來看看Eclipse的提示
在Eclipse中,提供兩種方式讓咱們快速添加SerialVersionUid。
add default serial version ID:
Adds a default serial version ID to the selected type
Use this option to add a user-defined ID in combination with custom serialization code if the type did undergo structural change since its first release.
Default 值是1L, 在可兼容的前提下,能夠保留舊版本號,若是不兼容,或者想讓它不兼容,就手工遞增版本號。
add generated serial version ID:
Adds a generated serial version ID to the selected type
Use this option to add a compiler-generated ID if the type didnot undergo structural change since its first release.
根據類的結構產生的hash值。增減一個屬性、方法等,均可能致使這個值產生變化。
適合場景
開發者認爲每次修改類後就須要生成新的版本號,不想向下兼容,操做就是刪除原有serialVesionUid聲明語句,再自動生成一下。
我的認爲default簡單。第二種可以保證每次更改類結構後改變版本號,雖然看上去很cool,實際上讓人很迷惑。
如何使用 serialVersionUID ?
What you should do is to change serialVersionUID (for example increase it by 1 or make your IDE generate automatically a new value) every time there is some change in the definition of data stored in the class. For example if you change data types, variable names or add new data – hence every time you want to have ‘backward incompatibility’ for deserialization.
Reference
http://stackoverflow.com/questions/6429462/java-static-serialization-rules
http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
http://stackoverflow.com/questions/285793/what-is-a-serialversionuid-and-why-should-i-use-it
http://www.javablogging.com/what-is-serialversionuid/
http://www.mkyong.com/java-best-practices/understand-the-serialversionuid/