Java SerialVersionUID作用詳解

問題1:Serializable是什麼

首先,說說Serializable是實現java將內存中的類存儲至硬盤中而使用的

一個類使用瞭Serializalbe接口,在序列化到文件時,會有一個SerialVersionUID。

這個東東是用於對類進行版本控制的。

首先看Person類清單:

=====

import  java.io.Serializable;
 
public  class  Person  implements  Serializable {
     
     //如果沒有指定serialVersionUID,系統會自動生成一個
     private  static  final  long  serialVersionUID = 1L;
     private  String name;
     //添加這麼一個成員變量  
     private  String address;    //序列化後如果之前版本沒有,就為null
 
     public  String getName() {
//      int a = 100;
//      for(int i=0;i<a;i++){
//          name+=i;
//      }
         return  name;
     }
     public  void  setName(String name) {
         this .name = name;
     }
}

===== 然後是測試類清單 =====

import  java.io.FileInputStream;
import  java.io.FileNotFoundException;
import  java.io.FileOutputStream;
import  java.io.IOException;
import  java.io.ObjectInputStream;
import  java.io.ObjectOutputStream;
 
/**
  * if Object implements Serializable without Uid,
  * system will automatically give this object a uid by algorithm
  * @author v11
  * @date 2014年9月18日
  * @version 1.0
  */
public  class  WhySerialversionUID {
 
     public  static  void  objectToFile(Object obj,String fileName)  throws  Exception{
         ObjectOutputStream oo =  new  ObjectOutputStream( new  FileOutputStream(
                 fileName));
         oo.writeObject(obj);
         oo.close();
     }
 
     public  static  Object getObjectFromFile(String fileName)  throws  Exception {
         ObjectInputStream oi =  new  ObjectInputStream( new  FileInputStream(
                 fileName));
         Person crab_back = (Person) oi.readObject();
         oi.close();
         return  crab_back;
     }
     public  static  void  main(String[] args)  throws  Exception {
         String fileName =  "crab_file" ; //文件名
         
         // 這裡是把對象序列化到文件
         Person crab =  new  Person();
         crab.setName( "Mr.Crab" );
         
         //儲存到文件中
         //objectToFile(crab,fileName);
 
         // 這裡是把對象序列化到文件,我們先註釋掉,一會兒用
         Person crabBack = (Person) getObjectFromFile(fileName);
         //Dog crabBack = (Dog) getObjectFromFile(fileName);
         System.out.println( "Hi, My name is "  + crabBack.getName());
 
     }
}

=====

1.對於Person類中,將變量 address和SerialVersionUID註釋掉,存儲到文件,並讀出。顯示正常

2.將變量address還原,讀取原來存儲的文件,顯示異常。拋出錯誤 InvalidClassException。

原因如下:

因為我們沒有指定SerialVersionUID,因此系統自動生成瞭一個serialVersionUID(這個是根據類名,變量名,方法名)生成的

但是改動後的Person中變量名有變動,於是這個UID就不一樣瞭,對於版本控制就無法讀取。

所以,大傢在很多代碼裡看到把UID設置為1L,就是Person代碼中那樣。

將Person代碼UID設置為1L,再重復上述步驟,不報錯。那麼就意味著如果你選擇將UID設置為1L,就是選擇瞭兼容類的版本不一致。

PS:為什麼說自動生成的 serialVersionUID是根據 類名,變量名,方法名,因為當你在原有的類的方法內進行添加內容,並不是對最後系統生成的UID造成影響,即不會拋出錯誤

問題2:所有類都設置為1L,是否有不良影響,不同類會不會沖突

public  class  Dog  implements  Serializable{
     
     private  static  final  long  serialVersionUID = 1L;
     private  String name;
     
     public  String getName() {
         return  name;
     }
 
     public  void  setName(String name) {
         this .name = name;
     }
     
}

新定義Dog類如上,將測試類代碼中Dog的賦值註釋去掉

 //Dog crabBack = (Dog) getObjectFromFile(fileName);

運行結果拋出錯誤:

Exception in thread “main” java.lang.ClassCastException: serializable.Person cannot be cast to serializable.Dog

說明serializable在不同類一間並不矛盾。

到此這篇關於Java SerialVersionUID作用詳解的文章就介紹到這瞭,更多相關Java SerialVersionUID內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: