Serialization and Deserialization in Java

Serialization in Java refers to the process of translating the state of an object to a byte stream. The serialization was introduced in Java 1.1. This process is also called Marshaling. It can be used to persist the state of an object to a disk, a database or to send over a network. The most important point is that the byte stream is platform-independent. Java supports Serialization with the interface serializable. A class whose state has to be persisted should implement the java.io.serializable interface.  The java.io.ObjectOutputStream contains the writeObject()method that can be used to write the byte stream to a file. The method has the signature

public final void writeObject(Object obj) throws IOException

Deserialization in Java

Deserialization in Java refers to the process of translating the byte stream to object. This process is just the reverse of serialization. java.io.ObjectInputStream contains the readObject() method which can be used to read from a byte stream. The method has the signature

public final Object readObject() throws IOException, ClassNotFoundException

Serialization and Deserialization are used in Hibernate, RMI, etc.

About the Serializable Interface

Serializable is an Annotation (earlier Marker Interface). An Annotation, similar to a Marker Interface, does not have any members but Annotation denotes that a class implementing it will have special functionality.

  • If the parent class has implemented Serializable interface then a child class need not implement it.
  • The members of the class declared static will not be serialized. Because static members are a part of a class and not every object. To ignore an instance variable from serialization, it should be declared transient. By doing so, while serializing, instead of the actual value, the default value of the type of the variable is serialized. 0 for int, for example.
  • If a class which has to be serialized has a reference to another class, the other class must also be serializable. If a class which has to be serialized, has an array of objects then all the elements in the array should be serializable too. Otherwise, a NotSerializable exception will be thrown.
  • While deserializing, the constructor of the object is never called.

An Example

Consider the following program.

import java.io.Serializable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

class noteItem implements Serializable {
    private static final long serialVersionUID = 1L;
    private String title;
    private String content;
    private int id;
    public noteItem(int id, String title, String content) {
        this.id = id;
        this.title = title;
        this.content = content;
    }
    @Override
    public String toString() {
        return "ID: "+this.id+"\nTitle: "+this.title+"\nContent: "+this.content+"\n";
    }
}
class notePad implements Serializable {
    private static final long serialVersionUID = 2L;
    private noteItem[] notes;
    private int count = 0;
    public  notePad(int capacity) {
        this.notes = new noteItem[capacity];
    }
    public void addNote(String title, String content) {
        for (int i = 0; i < notes.length; i++) {
            if (notes[i]==null) {
                notes[i] = new noteItem(count+1,title, content);
                count+=1;
                break;
            }
        }
    }
    public String getState() {
        String state = "";
        for (noteItem i : notes) {
            if (i!=null)
                state = state + i;
        }
        return state;
    }
}
class SerExample {
    public static void main (String[] args) {
        notePad n = new notePad(100);
        n.addNote("Title", "Content");
        n.addNote("Title1", "Content1");
        try {
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("notepad.ser"));
            out.writeObject(n);
            out.close();
        }
        catch (NullPointerException | IOException e) {
            System.out.println(e.getMessage());
        }
        try {
            ObjectInputStream in = new ObjectInputStream(new FileInputStream("notepad.ser"));
            notePad retrievedn = (notePad) in.readObject();
            in.close();
            System.out.println(retrievedn.getState());
        }
        catch (NullPointerException | IOException | ClassNotFoundException e) {
            System.out.println(e.getMessage());
        }
    }
}

This example is a simple implementation of a notepad. It serializes an object of notePad class containing an array of objects, notes and the methods getState() and addNote(). Every element in the array is of the type noteItem which is an object of a class that implements the serializable interface. Therefore all the elements of the array are serializable. Also, the class notePad has a reference to the class noteItem and the class noteItem implements the Serializable interface. Therefore all the objects of notePad are serializable. Finally, after invoking readObject() on the ObjectInputStream object, it should be cast to the type of its class, notePad in this example.

If the program is run, it produces the following output as expected.

ID: 1
Title: Title
Content: Content
ID: 2
Title: Title1
Content: Content1

In the above example, if the type of variable content in the class noteItem is altered and it is declared as transient, it’s value can’t be serialized. So the value of content will be null because it is of type String. It produces the following output as expected.

ID: 1
Title: Title
Content: null
ID: 2
Title: Title1
Content: null

Leave a Reply

Your email address will not be published.