理解serialVersionUID是什么?有什么用?如何生成?


如果您曾經實現過 Serializable接口,則必須遇到此警告消息
The serializable class xxx does not declare a static final serialVersionUID field of type long
那么......什么是serialVersionUID?
serialVersionUID用作Serializable類中的版本控件。如果您沒有顯式聲明serialVersionUID,JVM將根據您的Serializable類的各個方面自動為您執行此操作,如 Java(TM)對象序列化規范中所述
1. SerialVersionUID示例
上面的語句在開頭有點難以理解(至少我做過),讓我們開始一個例子來了解Serializable類如何使用SerialVersionUID來實現版本控制。
 
1.1 Address.java
serialVersionUID為1L的可序列化類。
import java.io.Serializable;
 
public class Address implements Serializable{
 
       private static final long serialVersionUID = 1L;
    
       String street;
       String country;
 
       public void setStreet(String street){
           this.street = street;
       }
 
       public void setCountry(String country){
           this.country = country;
       }
 
       public String getStreet(){
           return this.street;
       }
 
       public String getCountry(){
           return this.country;
       }
 
       @Override
       public String toString() {
           return new StringBuffer(" Street : ")
           .append(this.street)
           .append(" Country : ")
           .append(this.country).toString();
       }
}

 

 
1.2 WriteObject.java
將Address對象寫入/序列化為文件的簡單類 - “c:\\ address.ser”。
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
 
public class WriteObject{
 
    public static void main (String args[]) {
     
       Address address = new Address();
       address.setStreet("wall street");
       address.setCountry("united states");
 
       try{
 
        FileOutputStream fout = new FileOutputStream("c:\\address.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fout);   
        oos.writeObject(address);
        oos.close();
        System.out.println("Done");
 
       }catch(Exception ex){
           ex.printStackTrace();
       } 
    }
}

 

 
1.3 ReadObject.java
從文件中讀取/反序列化Address對象的簡單類 - “c:\\ address.ser”。
import java.io.FileInputStream;
import java.io.ObjectInputStream;
 
public class ReadObject{
 
   public static void main (String args[]) {
 
       Address address;
       
       try{
 
           FileInputStream fin = new FileInputStream("c:\\address.ser");
           ObjectInputStream ois = new ObjectInputStream(fin);
           address = (Address) ois.readObject();
           ois.close();
 
           System.out.println(address);
           
       }catch(Exception ex){
           ex.printStackTrace(); 
       } 
   }
}

 

2.測試
讓我們做一些測試來演示serialVersionUID的使用。
2.1相同的serialVersionUID
相同的serialVersionUID,在反序列化過程中沒有問題
javac Address.java javac WriteObject.java javac ReadObject.java java WriteObject java ReadObject Street : wall street Country : united states
復制
2.2不同的serialVersionUID
在Address.java中, 將serialVersionUID更改為2L(它是1L),然后再次編譯它。
javac Address.java java ReadObject java.io.InvalidClassException: Address; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2 ... at ReadObject.main(ReadObject.java:14)
 
“  InvalidClassException”會引發,因為您使用serialVersionUID“1L”編寫了一個序列化類,但嘗試使用更新的序列化類serialVersionUID“2L”將其檢索回來。
serialVersionUID必須在序列化和反序列化過程中匹配。
什么時候應該更新你的serialVersionUID?
如果使用對可序列化類的某些不兼容的Java類型更改更新序列化類,則必須更新serialVersionUID。
有關可序列化類的兼容和不兼容Java類型更改的詳細信息,請參閱 Java對象序列化規范。
3.默認的serialVersionUID有什么問題?
如果沒有聲明serialVersionUID,JVM將使用自己的算法生成默認的SerialVersionUID,您可以在 此處檢查算法。
默認的serialVersionUID計算對類詳細信息非常敏感,可能因不同的JVM實現而異,並且在反序列化過程中會導致意外的InvalidClassExceptions。
3.1客戶端/服務器環境
- 客戶端在Windows中使用SUN的JVM。
- 服務器在Linux中使用JRockit。
客戶端通過套接字向服務器發送帶有默認生成的serialVersionUID(例如123L)的可序列化類,服務器可以在反序列化過程中生成不同的serialVersionUID(例如124L),並引發意外的InvalidClassExceptions。
3.2文件/數據庫環境
- App#1在Windows中使用SUN的JVM。
- App#2在Linux中使用JRockit。
序列化允許保存到文件或數據庫中。App#1默認生成serialVersionUID(例如123L)將可序列化類存儲到數據庫中,而App#2可能在反序列化過程中生成不同的serialVersionUID(例如124L),並引發意外的InvalidClassExceptions。
您可以在此處查看 JVM實現列表
4.如何生成serialVersionUID
您可以使用JDK“  serialver”或Eclipse IDE自動生成serialVersionUID,詳見詳細信息
結論
SUN強烈建議開發人員聲明serialVersionUID以避免上面列出的不同JVM問題,但我建議您應該了解什么是序列化,serialVersionUID如何實現版本控制以及您的類需要使用序列化的原因。了解serialVersionUID概念優於任何推薦的盲目。
 
本文參考:https://www.mkyong.com/java-best-practices/understand-the-serialversionuid/
參考
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM