在很多應用中,需要對某些對象進行序列化,讓它們離開內存空間,入住物理硬盤,以便長期保存。比如最常見的是Web服務器中的Session對象,當有10萬用戶并發訪問,就有可能出現10萬個Session對象,內存可能吃不消,于是Web容器就會把一些seesion先序列化到硬盤中,等要用了,再把保存在硬盤中的對象還原到內存中,說白了,就是能將一個2進制文件變成內存中的對象。在JAVA中,要實現這種機制,只要實現Serializable接口就可以了,先看下面這個簡單例子,serialVersionUID稍后引出。我們先定義一個簡單的Person類,然后創建這個對象,最后序列化它到一個文件。
/*****(Person類)*******/
import java.io.Serializable;
public class Person implements Serializable {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/*****(將對象序列化到一個文件)*******/
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class WhySerialversionUID {
public static void main(String[] args) throws Exception {
Person person= new Person();
person.setName("jack");
ObjectOutputStream oo = new ObjectOutputStream (new FileOutputStream(new File("E://jack.test")));
oo.writeObject(person);
oo.close();
/*****(通過以下方法可以正常的將文件中保存的對象還原到內存中)*******/
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class WhySerialversionUID {
public static void main(String[] args) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:\\jack.test")));
Person person = (Person)ois.readObject();
String name= person.getName();
System.Out.Print("name is: "+name);
一切都那么順利,但是如果在序列化之后,Person這個類發生了改變呢?比如,多了一個成員變量。我們做如下試驗,還是先將對象序列化到一個文件中,之后在Person這個類中添加一個成員變量,如下:
import java.io.Serializable;
public class Person implements Serializable {
private String name;
//添加這么一個成員變量
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
之后,我們再去運行一下還原,就發現運行出錯了,會報如下錯誤:
Exception in thread “main” java.io.InvalidClassException: Person; local class incompatible: stream classdesc serialVersionUID = 8383901821872620925, local class serialVersionUID = -763618247875550322
意思就是說,文件流中的class和classpath中的class,也就是修改過后的class,不兼容了,處于安全機制考慮,程序拋出了錯誤,并且拒絕載入。那么如果我們真的有需求要在序列化后添加一個字段或者方法呢?應該怎么辦?那就是自己去指定serialVersionUID。之前,在我們的例子中,我們是沒有指定serialVersionUID的,那么java編譯器會自動給這個class進行一個摘要算法,類似于指紋算法,只要這個文件多一個空格,得到的UID就會截然不同的,可以保證在這么多類中,這個編號是唯一的。所以,我們添加了一個字段后,由于沒有顯指定serialVersionUID,編譯器又為我們生成了一個UID,當然和前面保存在文件中的那個不會一樣了,于是就出現了2個號碼不一致的錯誤。因此,只要我們自己指定了serialVersionUID,就可以在序列化后,去添加一個字段,或者方法,而不會影響到后期的還原,還原后的對象照樣可以使用,而且還多了方法可以用,呵呵。但是serialVersionUID我們怎么去生成呢?你可以寫1,也可以寫2,都無所謂,但是最好還是按照摘要算法,生成一個惟一的指紋數字,eclipse可以自動生成的,jdk也自帶了這個工具。一般寫法類似于
private static final long serialVersionUID = -763618247875550322L;在引用serializable這個類的前面有一個感嘆號,單擊這個感嘆號后會有提示,一個是默認的,一個為此類自動產生一個SerialVersionUID!
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/jimforme/archive/2010/01/02/5120587.aspx
浙公網安備 33010602011771號