DEV Community

Salad Lam
Salad Lam

Posted on • Updated on

More about Java Serialization

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

  1. The fact that all non static fields of serializable class must be serializable
  2. How to save/load object instance
  3. Define custom steps on save/load object instance
  4. The function of field "serialVersionUID"
  5. 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);
    }

}
Enter fullscreen mode Exit fullscreen mode

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();
    }

}
Enter fullscreen mode Exit fullscreen mode

Open file "classInstances.bin" by text editor.
content of classInstances.bin.png

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.");
        }
    }

}
Enter fullscreen mode Exit fullscreen mode

The printout is

ClassB restored, stored value is 4678
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)