serialVersionUID的作用
在很多應用中,需要對某些物件進行序列化,讓它們離開記憶體空間,入住物理硬碟,以便長期儲存。比如最常見的是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!
serialVersionUID作用:
序列化時為了保持版本的相容性,即在版本升級時反序列化仍保持物件的唯一性。
有兩種生成方式:
一個是預設的1L,比如:private static final long serialVersionUID = 1L;
一個是根據類名、介面名、成員方法及屬性等來生成一個64位的雜湊欄位,比如:
private static final long serialVersionUID = xxxxL;
當你一個類實現了Serializable介面,如果沒有定義serialVersionUID,Eclipse會提供這個
提示功能告訴你去定義 。在Eclipse中點選類中warning的圖示一下,Eclipse就會
自動給定兩種生成的方式。如果不想定義它,在Eclipse的設定中也
可以把它關掉的,設定如下:
Window ==> Preferences ==> Java ==> Compiler ==> Error/Warnings ==>
Potential programming problems
將Serializable class without serialVersionUID的warning改成ignore即可。
如果你沒有考慮到相容性問題時,就把它關掉,不過有這個功能是好的,只要任何類別實現了Serializable這個介面的話,如果沒有加入
serialVersionUID,Eclipse都會給你warning提示,這個serialVersionUID為了讓該類別
Serializable向後相容。
如果你的類Serialized存到硬碟上面後,可是後來你卻更改了類別的field(增加或減少或改名),當你Deserialize時,就會出現Exception的,這樣就會造成不相容性的問題。
但當serialVersionUID相同時,它就會將不一樣的field以type的預設值Deserialize,可避開不相容性問題。
相關文章
- serialVersionUID作用UI
- 序列化-serialVersionUID作用UI
- Java serialVersionUID 有什麼作用?JavaUI
- 靜態long型別常量serialVersionUID的作用型別UI
- Java之serialVersionUIDJavaUI
- Java中serialVersionUID的解釋JavaUI
- 自動生成serialVersionUIDUI
- Intellij Idea 生成serialVersionUID的方法IntelliJIdeaUI
- 深入理解Java序列化中的SerialVersionUidJavaUI
- 注意由雙大括號匿名類引起的serialVersionUID編譯告警UI編譯
- js的作用域、作用域鏈JS
- js的作用域和作用域鏈JS
- js的作用域與作用域鏈JS
- Java中的volatile的作用和synchronized作用Javasynchronized
- Symbol 的作用Symbol
- jQuery $ 的作用jQuery
- #include的作用
- Spring的作用域以及RequestContextListener作用SpringContext
- http 代理的作用HTTP
- JS的作用域JS
- Hashcode的作用
- Git分支的作用Git
- condition的作用
- 作用域的理解
- source命令的作用
- spring的作用Spring
- Oracle Undo的作用Oracle
- SMON 程式的作用
- __declspec(dllimport)的作用Import
- cookie的作用域Cookie
- SSH Agent 的作用
- noEmit 的作用是?MIT
- Kafka——zookeeper的作用Kafka
- ContentPresenter 的作用
- oracle的undo的作用Oracle
- Vue中key的作用Vue
- Symbol 的作用[翻譯]Symbol
- JAVA中initCause()的作用Java