Table of contents
1. What is serialVersionUID
The SerialVersionUID property is an identifier used to serialize/deserialize objects of a serializable class, we use the serialVersionUID property to remember the version of a serializable class to verify that the loaded class and the serialized object are compatible. If the receiver loads an object with a class serialVersionUID that differs from the corresponding sender's class, deserialization will result in an InvalidClassException.
Note: The serialVersionUID attributes of different classes are independent. Therefore, it is not necessary for different classes to have unique values.
2. Create a serialVersionUID
First create a serializable class and declare a serialVersionUID identifier:
public class Test implements Serializable {
private static final long serialVersionUID = 1L;
public String name;
public String password;
}
3. Use serialVersionUID
Next we create two classes, one for serialization and the other for deserialization.
3.1 Serialization example program
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());
}
}
Run SerializationUtility, save (serialize) the Test object into a String instance, and use Base64 to encode the bytes to get the following results:
3.2 Deserialization example program
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;
}
}
Use the above serialized String as the parameter of the deserialization method, run DeserializationUtility, and reassemble (deserialize) the Test object with the given String, and get the following results:
3.3 Serialization and deserialization when serialVersionUID is different
Let's just change the serialVersionUID of the previous Test, for example like this:
public class Test implements Serializable {
private static final long serialVersionUID = 2L;
public String name;
public String password;
}
Then run the deserialization program DeserializationUtility, get the following results:
why?
Because we modified the version/state of the class by changing its serialVersionUID. As a result, no compatible class was found during deserialization, and an InvalidClassException was thrown.
3.4 Can I not provide serialVersionUID?
If no serialVersionUID is provided in the Serialized class, the JVM will automatically generate one. However, it would be better to provide the serialVersionUID value and update it after class changes so that we can control the serialization/deserialization process.
In this case some changes to the class may break serialization compatibility.