什么是serialVersionUID?为什么要使用它?

一、什么是serialVersionUID

SerialVersionUID属性是用于序列化/反序列化可序列化类的对象的标识符,我们使用serialVersionUID属性来记住可序列化类的版本,以验证加载的类和序列化对象是否兼容。如果接收方为对象加载的类serialVersionUID与相应发送方的类不同,则反序列化将导致 InvalidClassException。

备注:不同类的serialVersionUID属性是独立的。因此,不同的类没有必要具有唯一的值。

二、创建一个serialVersionUID

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

public class Test implements Serializable {
    
    
    private static final long serialVersionUID = 1L;
    public String name;
    public String password;
}

三、使用 serialVersionUID

下来我们创建两个类,一个用以序列化,另一个用以反序列化。

3.1 序列化实例程序

public class SerializationUtility {
    
    

    public static void main(String[] args) {
    
    
        Test serial= new Test ();
        serial.name= "serial123";
        serial.password= "serial369";

        String serializedObj = serializeObjectToString(serial);
 
        System.out.println("Serialized Test 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());
    }
}

运行SerializationUtility,将Test对象保存(序列化)到String实例中,并使用Base64对字节进行编码,得到下面的结果:
在这里插入图片描述

3.2 反序列化实例程序

public class DeserializationUtility {
    
    
 
    public static void main(String[] args) {
    
    
 
        String serializedObj = ... // 省略
        System.out.println( "Deserializing Test...");
 
        Test deserializedObj = (Test) deSerializeObjectFromString( serializedObj);
 
         System.out.println( "Headphone port of Test: "+ deserializedObj.name);
        System.out.println(  "Thunderbolt port of Test: " + deserializedObj.password);
    }
 
    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;
    }
}

使用上面序列化的 String 作为反序列化方法的参数,运行DeserializationUtility,给定的String 重新组装(反序列化) Test对象,得到下面的结果:
在这里插入图片描述

3.3 serialVersionUID不同的情况下进行序列话和反序列化

我们随便改一下前面 Test 的serialVersionUID,比如这样子:

public class Test implements Serializable {
    
    
    private static final long serialVersionUID = 2L;
    public String name;
    public String password;
}

然后运行反序列化程序 DeserializationUtility ,得到下面的结果:

在这里插入图片描述

为什么会这样?
因为我们通过更改类的serialVersionUID,修改了它的版本/状态。结果反序列化的时候没有找到兼容的类,抛出了InvalidClassException。

3.4 能不能不提供serialVersionUID?

如果Serialized类中未提供serialVersionUID,JVM 将自动生成一个。但是,最好提供serialVersionUID值并在类更改后更新它,以便我们可以控制序列化/反序列化过程。

这种情况下如果类的一些更改可能会破坏序列化兼容性。

猜你喜欢

转载自blog.csdn.net/qq_35241329/article/details/131575136
今日推荐