Skip to main content
 首页 » 编程设计

介绍java中serialVersionUID

2022年07月19日160txw1958

介绍java中serialVersionUID

serialVersionUID 是java中可序列化类的唯一标识。在对象反序列化时使用,确保加载的类与序列化对象兼容。如果类不匹配,会抛出 InvalidClassException异常。

示例说明

首先创建一个序列化类,并声明serialVersionUID 标识:

public class AppleProduct implements Serializable {
    
 
    private static final long serialVersionUID = 1234567L; 
 
    public String headphonePort; 
    public String thunderboltPort; 
}

接下来,我们需要两个工具类:一个序列化AppleProduct 对象至字符串中,另一个从字符串中反序列化生成对象:

public class SerializationUtility { 
 
   public static void main(String[] args) { 
       AppleProduct macBook = new AppleProduct(); 
       macBook.headphonePort = "headphonePort2020"; 
       macBook.thunderboltPort = "thunderboltPort2020"; 
 
       String serializedObj = serializeObjectToString(macBook); 
 
       System.out.println("Serialized AppleProduct object to string:"); 
       System.out.println(serializedObj); 
   } 
 
   public static String serializeObjectToString(Serializable o) { 
       ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
       ObjectOutputStream oos = new ObjectOutputStream(baos); 
       oos.writeObject(o); 
       oos.close(); 
 
       return Base64.getEncoder().encodeToString(baos.toByteArray()); 
   } 
}
public class DeserializationUtility { 
 
   public static void main(String[] args) { 
 
       String serializedObj = ... // ommited for clarity 
       System.out.println( 
         "Deserializing AppleProduct..."); 
 
       AppleProduct deserializedObj = (AppleProduct) deSerializeObjectFromString( 
         serializedObj); 
 
       System.out.println( 
         "Headphone port of AppleProduct:" 
           + deserializedObj.getHeadphonePort()); 
       System.out.println( 
         "Thunderbolt port of AppleProduct:" 
          + deserializedObj.getThunderboltPort()); 
   }
   public static Object deSerializeObjectFromString(String s) 
     throws IOException, ClassNotFoundException { 
 
       byte[] data = Base64.getDecoder().decode(s); 
       ObjectInputStream ois = new ObjectInputStream( 
         new ByteArrayInputStream(data)); 
       Object o = ois.readObject(); 
       ois.close(); 
       return o; 
   } 
}

我们开始运行SerializationUtility,其保存(序列化)ApplProduct 为字符串实例,使用Base64编码。

然后运行DeserializationUtility类,使用之前生成的字符串作为deserialization 方法的参数,装配(反序列化)AppleProduct 对象。输出结果大致如下:

Serialized AppleProduct object to string: 
rO0ABXNyACljb20uYmFlbGR1bmcuZGVzZXJpYWxpemF0aW9uLkFwcGxlUHJvZHVjdAAAAAAAEta 
HAgADTAANaGVhZHBob25lUG9ydHQAEkxqYXZhL2xhbmcvU3RyaW5nO0wADmxpZ2h0ZW5pbmdQb3 
J0cQB+AAFMAA90aHVuZGVyYm9sdFBvcnRxAH4AAXhwdAARaGVhZHBob25lUG9ydDIwMjBwdAATd 
Gh1bmRlcmJvbHRQb3J0MjAyMA== 
 
Deserializing AppleProduct... 
Headphone port of AppleProduct:headphonePort2020 
Thunderbolt port of AppleProduct:thunderboltPort2020

现在,让我们修改AppleProduct类中的常量serialVersionUID,并尝试使用之前的字符串反序列化AppleProduct 对象,重新运行会抛出异常:

Deserializing AppleProduct... 
Exception in thread "main" java.io.InvalidClassException: com.dataz.deserialization.AppleProduct; local class incompatible: stream classdesc serialVersionUID = 1234567, local class serialVersionUID = 7654321 
    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616) 
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1630) 
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1521) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1781) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353) 
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373) 
    at com.baeldung.deserialization.DeserializationUtility.deSerializeObjectFromString(DeserializationUtility.java:24) 
    at com.dataz.deserialization.DeserializationUtility.main(DeserializationUtility.java:15)

改变类的serialVersionUID ,即修改类的版本/状态,因此在反序列化过程中类不兼容并抛出异常InvalidClassException 。

已存在类中增加新字段

现在我们需要增加lightningPort字段至已存在的类AppleProduct中:

public class AppleProduct implements Serializable {
    
//... 
    public String lightningPort; 
}

由于我们只是添加了一个新字段,所以不需要更改serialVersionUID。这是因为在反序列化过程中,lightningPort字段将被赋值null作为默认值。我们修改DeserializationUtility 类,增加打印新字段:

System.out.println("LightningPort port of AppleProduct:" 
  + deserializedObj.getLightningPort());

现在,当我们重新运行DeserializationUtility 类,输出结果如下:

Deserializing AppleProduct... 
Headphone port of AppleProduct:headphonePort2020 
Thunderbolt port of AppleProduct:thunderboltPort2020 
Lightning port of AppleProduct:null

总结

本文我们演示了使用serialVersionUID常量来实现序列化数据的版本化。


本文参考链接:https://blog.csdn.net/neweastsun/article/details/80295384