Menu
Topics Index
...
`


Input/Output: Exploring java.io > Serialization >
Siva Nookala - 15 Apr 2016
As discussed in Serialization In Java , the process of saving and restoring the object data is called Serialization. The interfaces Serialization In Java and Externalizable In Java with Example makes an object serializable. This process is used for storing data to files or for sending data over network.

The below program shows how an object of class which implements Serializable can be converted into bytes (serialization) and then it shows how it can be converted back from bytes into object (de-serialization).
Serializable Test
import java.io.*;

class SerializableTest
{
    public static void main(String[] args) throws IOException, ClassNotFoundException
    {
    
        // SERIALIZATION - START
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        Student hemanth = new Student();
        hemanth.name = "Hemanth";
        hemanth.rollNumber = 25;
        hemanth.section = 'C';
        System.out.println("Before - " + hemanth.name + " " + hemanth.rollNumber + " " + hemanth.section);
        oos.writeObject(hemanth); // LINE A
        oos.close();
        byte[] objectDataBytes = baos.toByteArray();
        // SERIALIZATION - END
    
        // DESERIALIZATION - START
        ByteArrayInputStream bais = new ByteArrayInputStream(objectDataBytes);
        ObjectInputStream ois = new ObjectInputStream(bais);
        Student hemanthRestored = (Student) ois.readObject(); // LINE B
        System.out.println("After - " + hemanthRestored.name + " " + hemanthRestored.rollNumber + " " + hemanthRestored.section);
        ois.close();
        // DESERIALIZATION - END
    }

}

class Student implements Serializable
{

    String name = "";
    int rollNumber = 0;
    char section = 'A'; // LINE C
}
OUTPUT

Before - Hemanth 25 C
After - Hemanth 25 C

DESCRIPTION

Here we are creating an ObjectOutputStream using an ByteArrayOutputStream. Then we are serializing the created hemanth object into the ObjectOutputStream at LINE A. By doing this the object data, basically "Hemanth", 25 and C are converted into bytes and then written into the output stream.
Later the converted bytes data is given as input to ByteArrayInputStream which in-turn is input to ObjectInputStream. At LINE B, using the ObjectInputStream the object data is read back or de-serialized. Since we know the read object is Student, we are type casting it to that class.
As you can see the data before serialization and the after serialization is same and both times it prints Hemanth 25 C.

THINGS TO TRY
  • Add one more variable percentage of type double to the Student class and initialize it 75.6. Change before and after println statements and see that the value 75.6 is retained even after the de-serialization process.
  • Make the section variable as transient, by adding the transient keyword before char at LINE C. See that the section will be changed to the default value of 'A'. As you know, transient variables will not be serialized.
Although time consuming, the serialization can be done using Externalizable interface as well. The below program discusses the same in detail.
Externalizable Test
import java.io.*;

class ExternalizableTest
{
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        Student hemanth = new Student("Hemanth", 25, 'C');
        System.out.println("Before - " + hemanth.name + " " + hemanth.rollNumber + " " + hemanth.section);
        oos.writeObject(hemanth); // LINE A
        oos.close();
        byte[] objectDataBytes = baos.toByteArray();
        ByteArrayInputStream bais = new ByteArrayInputStream(objectDataBytes);
        ObjectInputStream ois = new ObjectInputStream(bais);
        Student hemanthRestored = (Student) ois.readObject(); // LINE B
        System.out.println("After - " + hemanthRestored.name + " " + hemanthRestored.rollNumber + " " + hemanthRestored.section);
        ois.close();
    }
}

class Student implements Externalizable {

    String name = "";
    int rollNumber = 0;
    char section = 'A';

    // CONSTRUCTOR 1
    public Student() { }

    // CONSTRUCTOR 2
    public Student(String name, int rollNumber, char section) {
        super();
        this.name = name;
        this.rollNumber = rollNumber;
        this.section = section;
    }

    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        name = in.readUTF();
        rollNumber = in.readInt();
        // section = in.readChar(); // LINE X
    }

    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(name);
        out.writeInt(rollNumber);
        // out.writeChar(section); // LINE Y
    }
}
OUTPUT

Before - Hemanth 25 C
After - Hemanth 25 A

DESCRIPTION

Here we are creating an ObjectOutputStream using an ByteArrayOutputStream. Then we are serializing the created hemanth object into the ObjectOutputStream at LINE A. By doing this the object data, basically "Hemanth", 25 and C are converted into bytes and then written into the output stream.
Later the converted bytes data is given as input to ByteArrayInputStream which in-turn is input to ObjectInputStream. At LINE B, using the ObjectInputStream the object data is read back or de-serialized. Since we know the read object is Student, we are type casting it to that class.
As you can see the data before serialization and the after serialization is note same. This is because in the readExternal and writeExternal methods we are not taking care of section. That is why the value of section after de-serializing is set to the default value of 'A'. This way you can serialize only the member variables you want to serialize and ignore the rest. You can also change how the data is stored.

THINGS TO TRY
  • Uncomment LINE X and LINE Y and see that the section is also retained after the serialization and the value 'C' is printed.
  • Add one more variable percentage of type double to the Student class and initialize it 75.6. Change before and after println statements and see that the value 75.6 is not retained after the de-serialization process. This is because we have not added the code for writing and reading the percentage variable. Change the methods readExternal and writeExternal to handle percentage variable. Please use the methods writeDouble and readDouble for the same.
  • Remove the default constructor CONSTRUCTOR 1 and see that the readObject fails with InvalidClassException
  • Remove the type cast to Student at LINE B and see that we get a compilation error since readObject returns an Object and not Student.
  • Change the order of the method calls in readExternal and writeExternal and see that if we do not use the same order in both the methods, then we might get inconsistent data or run-time errors.

0
Wrong
Score more than 2 points

© meritcampus 2019

All Rights Reserved.

Open In App