https://www.baeldung.com/java-serial-version-uid

1. 概述

serialVersionUID属性是用于序列化/反序列化*Serializable*类的对象的标识符。

在本快速教程中,我们将通过示例讨论什么是serialVersionUID以及如何使用它。

2. 序列版本 UID

简单地说,我们使用 serialVersionUID 属性来记住 Serializable 类的版本,以验证加载的类和序列化对象是否兼容。

不同类的serialVersionUID属性是独立的。因此,不同的类不需要具有唯一的值。

接下来我们通过一些示例来学习如何使用 serialVersionUID 。

让我们首先创建一个可序列化的类并声明一个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.java ,它将AppleProduct对象保存(序列化)为String实例,并使用Base64对字节进行编码。

然后,使用该字符串作为反序列化方法的参数,我们运行DeserializationUtility.java,它从给定的字符串重新组合(反序列化)AppleProduct对象。

生成的输出应类似于此:

Serialized AppleProduct object to string:
rO0ABXNyACljb20uYmFlbGR1bmcuZGVzZXJpYWxpemF0aW9uLkFwcGxlUHJvZHVjdAAAAAAAEta
HAgADTAANaGVhZHBob25lUG9ydHQAEkxqYXZhL2xhbmcvU3RyaW5nO0wADmxpZ2h0ZW5pbmdQb3
J0cQB+AAFMAA90aHVuZGVyYm9sdFBvcnRxAH4AAXhwdAARaGVhZHBob25lUG9ydDIwMjBwdAATd
Gh1bmRlcmJvbHRQb3J0MjAyMA==

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

现在,让我们修改AppleProduct.java 中的serialVersionUID 常量,并重新尝试从之前生成的相同字符串反序列化AppleProduct对象。重新运行DeserializationUtility.java应该会生成此输出。

Deserializing AppleProduct...
Exception in thread "main" java.io.InvalidClassException: com.baeldung.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.baeldung.deserialization.DeserializationUtility.main(DeserializationUtility.java:15)