標籤:des style blog http color io os 使用 java
如果某個 class implements Serializable,Eclipse 會提示產生 serialVersionUID ,多數情況下,我都選擇是。可這個東西到底是什麼呢?
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。
寫一個測試類別,試試 serialize and deserialize Item
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); //--1test.readFromDisk(name); // --2}catch(Exception e){e.printStackTrace();} }}
運行結果
101
完全正確!
看看D盤,有個檔案out.dat. 關閉寫檔案,直接讀取 out.dat
運行結果
101
試試把 serialVersionUID = 2L
private static final long serialVersionUID = 2L;
再運行
java.io.InvalidClassException: com.home.demo.Item; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
噢。。。。 出錯了!
根據 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進行最簡單的檢驗和控制。
如何正確使用 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/
Serializable and serialVersionUID