目录
一、什么是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值并在类更改后更新它,以便我们可以控制序列化/反序列化过程。
这种情况下如果类的一些更改可能会破坏序列化兼容性。