Notice
I wrote this article and was originally published on Qiita on 11 July 2022.
About Serialization interface
There is a brief introduction on baeldung to discuss on Serialization interface. Which includes
- The fact that all non static fields of serializable class must be serializable
- How to save/load object instance
- Define custom steps on save/load object instance
- The function of field "serialVersionUID"
- The function of keyword "transient"
About writeReplace() and readResolve() function
Example
Please read the following example. There is a serializable ClassB field clazz in serializable class ClassA. And ClassB stores a interger value.
public class ClassA implements Serializable {
private static final long serialVersionUID = -3820915223873146953L;
private ClassB clazz;
public ClassA(ClassB clazz) {
this.clazz = clazz;
}
public ClassB getClazz() {
return clazz;
}
public void setClazz(ClassB clazz) {
this.clazz = clazz;
}
}
public class ClassB implements Serializable {
private static final long serialVersionUID = -3228753062737301225L;
private int store = 0;
public ClassB(int store) {
this.store = store;
}
public int getStore() {
return store;
}
private Object writeReplace() throws ObjectStreamException {
return new ClassBReplaced(this.store);
}
}
public class ClassBReplaced implements Serializable {
private static final long serialVersionUID = -43981721356007654L;
private int store = 0;
public ClassBReplaced(int store) {
this.store = store;
}
public int getStore() {
return store;
}
private Object readResolve() throws ObjectStreamException {
return new ClassB(this.store);
}
}
Then serialize ClassA instance by following code.
public class SerializationTest {
public static void main(String[] args) throws IOException {
ClassB obj1 = new ClassB(4678);
ClassA obj2 = new ClassA(obj1);
FileOutputStream fileOutputStream = new FileOutputStream("classInstances.bin");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(obj2);
objectOutputStream.flush();
objectOutputStream.close();
}
}
Open file "classInstances.bin" by text editor.
Instance of class ClassBReplaced is written to field "clazz". And then try to restore the instance by following code.
public class DeserializationTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream fileInputStream = new FileInputStream("classInstances.bin");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
ClassA obj1 = (ClassA) objectInputStream.readObject();
objectInputStream.close();
if (obj1.getClazz() instanceof ClassB) {
System.out.println("ClassB restored, stored value is " + obj1.getClazz().getStore());
} else {
System.out.println("ClassB is not restored.");
}
}
}
The printout is
ClassB restored, stored value is 4678
Instance of ClassB restored successfully without data loss.
Usage
writeReplace() and readResolve() function is defined on Serialization interface. When there is some reason that it is impossible to serialize instance of ClassB (for example very complex class), writeReplace() is defined for creating serializable, data recording instance ClassBReplaced. And in ClassBReplaced, readResolve() is defined to recreate instance of ClassB by using information contained when deserialization.