Java Serialization with Inheritance

In my previous tutorial we have seen the basics of Java Serialization with some examples; in this tutorial we will see one important concept, which is Java Serialization with Inheritance. Here we are going to discuss two important scenarios with respect to Serialization, one is how a Serialization will happen if superclass is serialized but subclass is not serialized. Second, how a Serialization will happen if superclass is not serialized but subclass is serialized.

Java Serialization with Inheritance

Java Serialization with Inheritance

Scenario 1: Parent class has Serializable interface but child class doesn’t have Serializable Interface.

If parent class implements Serializable Interface, but child class doesn’t implement Serializable interface, then we can serialize child class object as well. Because if parent class has serializable behavior then by default child class also will have serializable behavior.

Father.java

package com.learnfromexamples.serialization.inheritances;

import java.io.Serializable;

public class Father implements Serializable{

 int parent = 1;
 public Father() {
 System.out.println("Father Constructor...");
 parent = 3;
 }
 {
 parent = 2;
 System.out.println("Instance Block....");
 }

}

Son.java

package com.learnfromexamples.serialization.inheritances;

public class Son extends Father{
 int child = 4;
 public Son() {
 System.out.println("Son Constructor...");
 child = 5;
 }
 {
 child=6;
 }
}

SerializationInheritanceDemo.java

package com.learnfromexamples.serialization.inheritances;

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

public class SerializationInheritanceDemo {

 public static void main(String[] args) throws IOException, ClassNotFoundException {
 Son son = new Son();
 son.child = 11;
 son.parent = 21;
 System.out.println("Serialization Starts");
 FileOutputStream fileOutputStream = new FileOutputStream("inheritance.txt");
 ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
 objectOutputStream.writeObject(son);
 
 System.out.println("DeSerialization Starts");
 FileInputStream fileInputStream = new FileInputStream("inheritance.txt");
 ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
 Son son1 = (Son)inputStream.readObject();
 
 System.out.println(son1.child);
 System.out.println(son1.parent);
 }

}

Output

Instance Block....
Father Constructor...
Son Constructor...
Serialization Starts
DeSerialization Starts
11
21

Key points from the above example

We have a Father class and child class, so during instantiation; instance block and constructor will be executed and values got assigned; again we have changed the father value to 11 and child value to 21 and started performing serialization. So in deserialization process, we will get the same value as 11 and 21.

Scenario 2: Parent class doesn’t have Serializable interface but child class have Serializable Interface

Before going to discuss about this, we should know one important thing in Java. We all know that Object class is the base class for all the Java classes. Whether Object class implements Serializable interface? The answer to this question is No.

#1 Good to Know in Java Serialization with Inheritance

Object class doesn’t implement Serializable interface

So we can very well serialize child class object even if parent class doesn’t implement Serializable Interface. But JVM will follow some rules during serialization and deserialization process for this scenario.

Serialization Rule

During serialization process, if any instance variable is inherited from non serializable parent class, then JVM will ignore the normal value instead it will store the default value for that variable.

Deserialization Rule

During deserialization process, if we have any non serializable parent class, then JVM will perform following things for that non-serializable parent class.

  1. Variable Initialization will be done.
  2. Instance block will be executed.
  3. No-argument constructor will be executed.

We all know that during deserialization process, constructor should not be called. But if we have a non serializable parent class then there will be an exception case like this.  The below diagram will explain clearly about serialization and deserialization process.

Java Serialization with Inheritance - learnfromexamples

Java Serialization with Inheritance – learnfromexamples

Father.java

package com.learnfromexamples.serialization.inheritance;

public class Father {

 int parent = 1;
 public Father() {
 System.out.println("Father Constructor");
 parent = 3;
 }
 {
 System.out.println("Initialization Block..");
 parent = 2;
 }
}

Son.java

package com.learnfromexamples.serialization.inheritance;

import java.io.Serializable;

public class Son extends Father implements Serializable{

 public Son() {
 System.out.println("Son Constructor...");
 }
 int child = 4;
}

Serialization.java

package com.learnfromexamples.serialization.inheritance;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Serialization {

 public static void main(String[] args) throws IOException, ClassNotFoundException{
 Son son = new Son();
 son.parent = 101;
 son.child = 102;
 FileOutputStream fileOutputStream = new FileOutputStream("son.ser") ;
 ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
 objectOutputStream.writeObject(son);

 }

}

Output

Initialization Block..
Father Constructor
Son Constructor...

DeSerialization.java

package com.learnfromexamples.serialization.inheritance;

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

public class DeSerialization {

 public static void main(String[] args) throws IOException, ClassNotFoundException{
 
 FileInputStream fileInputStream = new FileInputStream("son.ser");
 ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
 Son sonDeseralized = (Son)inputStream.readObject();
 System.out.println(sonDeseralized.parent);
 System.out.println(sonDeseralized.child);
 }

}

Output

Initialization Block..
Father Constructor
3
102

Key Points from the above example

After instantiation, parent value will be 3 and son value will be 4, again we changed the values to 101 and 102 and started performing Serialization. During serialization, the parent value will be saved with default value, i.e 0 since it’s inherited from non serializable parent class.

During deserialization for non serializable parent class; instance variable initialization, instance block execution, no-argument constructor execution will be done and values got re-assigned to 3 instead of 101.

#2 Good to Know in Java Serialization with Inheritance

During deserialization, If non serializable parent class doesn’t have no-argument constructor, then we will get java.io.InvalidClassException. So its developer responsibility to include no-argument constructor

If you have any query on this Java Serialization with Inheritance tutorial, please comment your questions in the comment box. If you like this tutorial please share this tutorial with your friends and also provide a feedback by providing the comment.

Java Serialization – Complete Tutorial with Example for Beginners

What is Java Serialization?

The process of converting the data or object into a specific format and stores into a file or database or transfer the converted data into a network. In Java terminology, we can say that as transfer an Object(s) into a stream of bytes and store into a file or memory. In Java everything we deal with objects but if we want to transfer those objects over network then we are having some complications in sending the data as an object over network. Because Object might be lost, Object state might be changed etc. So in order to avoid these difficulties we can use Java Serialization to convert the object(s) into stream of bytes or some other format and transfer over a network. So by using Java Serialization we can persists the state of an Object(s).

 Java Serialization

Java Serialization

What is Java Deserialization?

Reverse process of Serialization is De-Serialization i.e. Reconstructing the Java object by reading the stream of bytes.

 

Java Serialization and Deserialization

Java Serialization and Deserialization

 

How Java Serialization and Deserialization is achieved

In Java the serialization is achieved by following the below key rules.

  1. Implement the Serializable interface.
  2. Maintain two methods, ObjectOutputStream writeObject method to serialize the object and write it into a stream, ObjectInputStream readObject method to read the object from stream and to deserialize it.

Java Serialization – Example

Student.java

package com.learnfromexamples.serialization;

import java.io.Serializable;

public class Student implements Serializable{
    
    private int studentRollNo;
    private String studentName;
    private String studentAddress;
    
    public Student(int studentRollNo, String studentName, String studentAddress) {
        System.out.println("Student Constructor...");
        this.studentRollNo = studentRollNo;
        this.studentName = studentName;
        this.studentAddress = studentAddress;
    }

    public int getStudentRollNo() {
        return studentRollNo;
    }

    public void setStudentRollNo(int studentRollNo) {
        this.studentRollNo = studentRollNo;
    }

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public String getStudentAddress() {
        return studentAddress;
    }

    public void setStudentAddress(String studentAddress) {
        this.studentAddress = studentAddress;
    }

    @Override
    public String toString() {
        return "Student [studentRollNo=" + studentRollNo + ", studentName=" + studentName + ", studentAddress="
                + studentAddress + "]";
    }
    
}

StudentSerializationImplementation.java

package com.learnfromexamples.serialization;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class StudentSerializationImplementation {

    public static void main(String[] args) throws IOException {
        Student student = new Student(25, "Sridhar", "Chennai");
        System.out.println(student);
        FileOutputStream fileOutputStream;
        try {
            fileOutputStream = new FileOutputStream("student.ser");
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(student);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

StudentDeSerializationImplementation.java

 
package com.learnfromexamples.serialization;

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

public class StudentDeSerializationImplementation {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileInputStream fileInputStream = new FileInputStream("student.ser");
        ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
        Student student = (Student)inputStream.readObject();
        System.out.println("De-Serialized Object");
        System.out.println(student);
    }

}

Output

De-Serialized Object
Student [studentRollNo=25, studentName=Sridhar, studentAddress=Chennai]

Let’s see the details of this example.

I have decided to serialize the Student class, so to perform Serialization in Java we must implement an interface called Serializable. Since Serializable is a marker interface, we haven’t overridden any of the methods.

To perform Serialization we have called a method “writeObject()”. This method serializes the Student object and writes the Serialized Objects into a file. The file will be created like below. If we open the file then we could see the Serialized content but those content won’t be understand by us.

Similarly to deserialize the content, we have called “readObject()” method. This method returns Object as a reference and we have type casted to Student instance.

Java Serialization -Serialized File

Java Serialization -Serialized File

NotSerializableException

In the above example, we have implemented the Serializable interface for Student object, so it’s very easy for Java to Convert Java Object into stream of byes. But if we forgot to implement Serializable interface for the object which we want to Serialize, then during runtime NotSerializableException will be thrown.

Java Serialization Good to Know 1

NotSerializableException is a RunTime Exception not a compile time exception.

Deserialization Won’t Invoke/Call Constructor

In the above example, we must have to note one important thing. During Java Serialization, Student Constructor is called. But during Deserialization Student Constructor is not called, because deserialization means reconstructing the serialized object, it’s not recreating the new object. So again if constructor is called then there is a possibility of changing the state of an object which has been serialized or saved.

Java Serialization for Secondary Type

In the above example, we have serialized all the variables which are of Primitive types, but how the serialization will happen if we have Complex or Secondary type. Consider the below snippet. In the Student class, we have a reference variable which is of another type called “Course”.

Course.java

package com.learnfromexamples.serialization;

public class Course {

    private int courseId;
    private String courseName;
    private double courseCost;
    
    public Course(int courseId, String courseName, double courseCost) {
        System.out.println("Course Constructor...");
        this.courseId = courseId;
        this.courseName = courseName;
        this.courseCost = courseCost;
    }
    public int getCourseId() {
        return courseId;
    }
    public void setCourseId(int courseId) {
        this.courseId = courseId;
    }
    public String getCourseName() {
        return courseName;
    }
    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }
    public double getCourseCost() {
        return courseCost;
    }
    public void setCourseCost(double courseCost) {
        this.courseCost = courseCost;
    }

    @Override
    public String toString() {
        return "Course [courseId=" + courseId + ", courseName=" + courseName + ", courseCost=" + courseCost + "]";
    }
}

Student.java

package com.learnfromexamples.serialization;

import java.io.Serializable;

public class Student implements Serializable{
    
    private int studentRollNo;
    private String studentName;
    private String studentAddress;
    private Course course;
    public Student(int studentRollNo, String studentName, String studentAddress, Course course) {
        System.out.println("Student Constructor...");
        this.studentRollNo = studentRollNo;
        this.studentName = studentName;
        this.studentAddress = studentAddress;
        this.course = course;
    }

    public int getStudentRollNo() {
        return studentRollNo;
    }

    public void setStudentRollNo(int studentRollNo) {
        this.studentRollNo = studentRollNo;
    }

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public String getStudentAddress() {
        return studentAddress;
    }

    public void setStudentAddress(String studentAddress) {
        this.studentAddress = studentAddress;
    }

    
    public Course getCourse() {
        return course;
    }

    public void setCourse(Course course) {
        this.course = course;
    }

    @Override
    public String toString() {
        return "Student [studentRollNo=" + studentRollNo + ", studentName=" + studentName + ", studentAddress="
                + studentAddress + ", course=" + course + "]";
    }
}

How the Serialization will happen for Course object? Whether developers have to explicitly serialize all the reference variables as well? The answer to all this question is “No”, because Java serialization will take care of serializing all the reference variables as well. So if we Serialize the Student Object, then automatically the course object also will be serialized, similarly if Course object contains reference to another variable, that object also will be automatically serialized by java. So we have to concentrate on serializing the “Student” object alone.

Again we must have to follow one key rule to serialize the reference variable, even though Java Serialization takes care of serializing the reference objects, its Java developer responsibility to implement Serializable interface for all reference variables as well, or else we will get NotSerializableException like below.

StudentSerializationImplementation.java

package com.learnfromexamples.serialization;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class StudentSerializationImplementation {

    public static void main(String[] args) throws IOException {
        Course course = new Course(1, "Java Serialization", 500);
        Student student = new Student(25, "Sridhar", "Chennai", course);
        
        System.out.println(student);
        FileOutputStream fileOutputStream;
        try {
            fileOutputStream = new FileOutputStream("student.ser");
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(student);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

Output

Course Constructor...
Student Constructor...
Student [studentRollNo=25, studentName=Sridhar, studentAddress=Chennai, course=Course [courseId=1, courseName=Java Serialization, courseCost=500.0]]
Exception in thread "main" java.io.NotSerializableException: com.learnfromexamples.serialization.Course
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at com.learnfromexamples.serialization.StudentSerializationImplementation.main(StudentSerializationImplementation.java:19)

But what would happen if we don’t access to Course class source code? Because only if we have access then only we can make that class into a Serializable class by implementing Serializable interface, or else runtime exception will be thrown and Serialization won’t be happen. How can we overcome all this shortcomings? To overcome this shortcoming, we should know some more concepts in Java Serialization.

What is Transient in Java

If we don’t want any of the variable/reference to be serialized then we can define those variables as transient. Hence during serialization, those variable(s) will be avoided. This is mainly used to avoid serializing the sensitive data. So during serialization process, all transient variables are stored with default values.

Employee.java

package com.learnfromexamples.serialization;

import java.io.Serializable;

public class Employee implements Serializable{

    private int empNo;
    private String empName;
    private transient String empPassword;
    
    public Employee(int empNo, String empName, String empPassword) {
        this.empNo = empNo;
        this.empName = empName;
        this.empPassword = empPassword;
    }
    public int getEmpNo() {
        return empNo;
    }
    public void setEmpNo(int empNo) {
        this.empNo = empNo;
    }
    public String getEmpName() {
        return empName;
    }
    public void setEmpName(String empName) {
        this.empName = empName;
    }
    public String getEmpPassword() {
        return empPassword;
    }
    public void setEmpPassword(String empPassword) {
        this.empPassword = empPassword;
    }
    @Override
    public String toString() {
        return "Employee [empNo=" + empNo + ", empName=" + empName + ", empPassword=" + empPassword + "]";
    }
    
}

TransientDemo.java

package com.learnfromexamples.serialization;

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

public class TransientDemo {

    public static void main(String[] args) throws IOException, ClassNotFoundException{
        Employee employee = new Employee(1, "Sridhar", "Sridhar");
        FileOutputStream fileOutputStream = new FileOutputStream("Employee.txt");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(employee);
        System.out.println("Serialization |:"+employee);
        
        FileInputStream fileInputStream = new FileInputStream("Employee.txt");
        ObjectInputStream objectInputStream =  new ObjectInputStream(fileInputStream);
        Employee employee2  = (Employee)objectInputStream.readObject();
        System.out.println("DeSerialization |:"+employee2);
    }
}

Output

Serialization :Employee [empNo=1, empName=Sridhar, empPassword=Sridhar]
DeSerialization :Employee [empNo=1, empName=Sridhar, empPassword=null]

In the above example, we could see employee password was not serialized and it has been saved with default value i.e null.

Now let go back to our previous Student example, in our Student class, we have a reference to Course object. So during serialization process, even Course object must implements Serializable interface to participate in Serialization, else NotSerializableException will be thrown. But if we don’t have access to Course class source code then we can’t make that Serializable. So in order to avoid that we can make that Course object as transient, hence during serialization process, it will avoid serializing Course object and a default null value will be stored.

Student.java

package com.learnfromexamples.serialization;

import java.io.Serializable;

public class Student implements Serializable{
    
    private int studentRollNo;
    private String studentName;
    private String studentAddress;
    private transient Course course;
    public Student(int studentRollNo, String studentName, String studentAddress, Course course) {
        System.out.println("Student Constructor...");
        this.studentRollNo = studentRollNo;
        this.studentName = studentName;
        this.studentAddress = studentAddress;
        this.course = course;
    }

    public int getStudentRollNo() {
        return studentRollNo;
    }

    public void setStudentRollNo(int studentRollNo) {
        this.studentRollNo = studentRollNo;
    }

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public String getStudentAddress() {
        return studentAddress;
    }

    public void setStudentAddress(String studentAddress) {
        this.studentAddress = studentAddress;
    }

    
    public Course getCourse() {
        return course;
    }

    public void setCourse(Course course) {
        this.course = course;
    }

    @Override
    public String toString() {
        return "Student [studentRollNo=" + studentRollNo + ", studentName=" + studentName + ", studentAddress="
                + studentAddress + ", course=" + course + "]";
    }
}

Course.java

/**
 * 
 */
package com.learnfromexamples.serialization;

import java.io.Serializable;

public class Course implements Serializable{

    private int courseId;
    private String courseName;
    private double courseCost;
    public Course(int courseId, String courseName, double courseCost) {
        System.out.println("Course Constructor...");
        this.courseId = courseId;
        this.courseName = courseName;
        this.courseCost = courseCost;
    }
    
    public int getCourseId() {
        return courseId;
    }
    public void setCourseId(int courseId) {
        this.courseId = courseId;
    }
    public String getCourseName() {
        return courseName;
    }
    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }
    public double getCourseCost() {
        return courseCost;
    }
    public void setCourseCost(double courseCost) {
        this.courseCost = courseCost;
    }

    @Override
    public String toString() {
        return "Course [courseId=" + courseId + ", courseName=" + courseName + ", courseCost=" + courseCost + "]";
    }
}

StudentSerializationImplementation.java

package com.learnfromexamples.serialization;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class StudentSerializationImplementation {

    public static void main(String[] args) throws IOException {
        Course course = new Course(1, "Java Serialization", 500);
        Student student = new Student(25, "Sridhar", "Chennai", course);
        
        System.out.println(student);
        FileOutputStream fileOutputStream;
        try {
            fileOutputStream = new FileOutputStream("student.ser");
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(student);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Output

Course Constructor...
Student Constructor...
Student [studentRollNo=25, studentName=Sridhar, studentAddress=Chennai, course=Course [courseId=1, courseName=Java Serialization, courseCost=500.0]]

StudentDeSerializationImplementation.java

package com.learnfromexamples.serialization;

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

public class StudentDeSerializationImplementation {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileInputStream fileInputStream = new FileInputStream("student.ser");
        ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
        Student student = (Student)inputStream.readObject();
        System.out.println("De-Serialized Object");
        System.out.println(student);
    }
}

Output

De-Serialized Object
Student [studentRollNo=25, studentName=Sridhar, studentAddress=Chennai, course=null]

During deserialization process, we could notice two things; both the Student and Course constructors are not called. As well as course object are set as null, since we marked that object as transient. Even though using transient keyword, we have avoided NotSerializableException, but if we perform any operation from de-serialized Course object, then we will get NullPointerException. So if we want to serialize the reference object for which we don’t have access to source code, then we must go for custom serialization mechanism. But before going to see about that, we have to see one more concepts about Java Serialization.

Java Serialization – Good to Know 2

We can serialize more than one object at a time. But during deserialization, we have to read it in the same order which we wrote. If we haven’t read the objects in the same order then ClassCastException will be thrown.

House.java

package com.learnfromexamples.serialization;

import java.io.Serializable;

public class House implements Serializable{
    private int houseNumber;
    public House(int houseNumber) {
        System.out.println("House Constructor...");
        this.houseNumber = houseNumber;
    }
    public int getHouseNumber() {
        return houseNumber;
    }
    public void setHouseNumber(int houseNumber) {
        this.houseNumber = houseNumber;
    }
    @Override
    public String toString() {
        return "House [houseNumber=" + houseNumber + "]";
    }
}

Flat.java

package com.learnfromexamples.serialization;

import java.io.Serializable;

public class Flat implements Serializable{
    private int flatNumber;
    public Flat(int flatNumber) {
        System.out.println("Flat Constructor...");
        this.flatNumber = flatNumber;
    }
    public int getFlatNumber() {
        return flatNumber;
    }
    public void setFlatNumber(int flatNumber) {
        this.flatNumber = flatNumber;
    }
    @Override
    public String toString() {
        return "Flat [flatNumber=" + flatNumber + "]";
    }
}

Bungalow.java

package com.learnfromexamples.serialization;

import java.io.Serializable;

public class Bungalow implements Serializable{

    private int bungalowNumber;
    public Bungalow(int bungalowNumber) {
        System.out.println("Bungalow Constructor...");
        this.bungalowNumber = bungalowNumber;
    }
    public int getBungalowNumber() {
        return bungalowNumber;
    }
    public void setBungalowNumber(int bungalowNumber) {
        this.bungalowNumber = bungalowNumber;
    }
    @Override
    public String toString() {
        return "Bungalow [bungalowNumber=" + bungalowNumber + "]";
    }
}

SerializationDemo.java

package com.learnfromexamples.serialization;

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

public class SerializationDemo {

    public static void main(String[] args) throws IOException, ClassNotFoundException{
        House house = new House(5);
        Flat flat = new Flat(6);
        Bungalow bungalow = new Bungalow(9);
        FileOutputStream fileOutputStream = new FileOutputStream("multipleobjects.txt");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(house);
        objectOutputStream.writeObject(flat);
        objectOutputStream.writeObject(bungalow);
        
        FileInputStream fileInputStream = new FileInputStream("multipleobjects.txt");
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        House house2 = (House)objectInputStream.readObject();
        Flat flat2 = (Flat)objectInputStream.readObject();
        Bungalow bungalow2 = (Bungalow)objectInputStream.readObject();
        
        System.out.println(house2);
        System.out.println(flat2);
        System.out.println(bungalow2);
    }

}

Output

House Constructor...
Flat Constructor...
Bungalow Constructor...
House [houseNumber=5]
Flat [flatNumber=6]
Bungalow [bungalowNumber=9]

But if we don’t know the order in which the Serialization has happened, then it’s better to use instanceof operator to read the object during deserialization.

package com.learnfromexamples.serialization;

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

public class SerializationDemo {

    public static void main(String[] args) throws IOException, ClassNotFoundException{
        House house = new House(5);
        Flat flat = new Flat(6);
        Bungalow bungalow = new Bungalow(9);
        FileOutputStream fileOutputStream = new FileOutputStream("multipleobjects.txt");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(house);
        objectOutputStream.writeObject(flat);
        objectOutputStream.writeObject(bungalow);
        
        FileInputStream fileInputStream = new FileInputStream("multipleobjects.txt");
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        Object object = objectInputStream.readObject();
        if(object instanceof House){
            House house2 = (House)object;
            System.out.println(house2);
        }else if(object instanceof Bungalow){
            Bungalow bungalow2 = (Bungalow)object;
            System.out.println(bungalow2);
        }else if(object instanceof Flat){
            Flat flat2 = (Flat)object;
            System.out.println(flat2);
        }
                
    }

}

Output

House Constructor...
Flat Constructor...
Bungalow Constructor...
House [houseNumber=5]

Now again we get back to our old Student example to perform Custom Serialization Mechanism and see how reference object can be serialized.

Include writeObject and readObject

In order to serialize the reference variable for which we don’t have access to source code, we have to manually write that state of variable during serialization. Also during deserialization manually we have to read the object which we have written.

writeObject: This method is used to manually write or add the state of a variable during serialization.

readObject: This method is used to manually read the state of an object during deserialization.

Also we have to make sure that whenever we read the state of an object, we have to read it in the same order we wrote, else ClassCastException will be thrown as we discussed early.

Java Serialization – Good to Know 3

Even though we manually write/read the state on object, we don’t have to call this method explicitly. Since this writeObject/readObject methods are callback methods, so JVM will automatically call these methods during Serialization and Deserialization.

Department.java

package com.learnfromexamples.serialization.customserialization;

public class Department {

    private int deptNo;
    private String deptName;
    public Department(int deptNo, String deptName) {
        System.out.println("Department Constructor...");
        this.deptNo = deptNo;
        this.deptName = deptName;
    }
    public int getDeptNo() {
        return deptNo;
    }
    public void setDeptNo(int deptNo) {
        this.deptNo = deptNo;
    }
    public String getDeptName() {
        return deptName;
    }
    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }
    @Override
    public String toString() {
        return "Department [deptNo=" + deptNo + ", deptName=" + deptName + "]";
    }
}

Lecture.java

package com.learnfromexamples.serialization.customserialization;

public class Lecture {
    private int lectureId;
    private String lectureName;
    public Lecture(int lectureId,  String lectureName) {
        System.out.println("Lecture Constructor...");
        this.lectureId = lectureId;
        this.lectureName = lectureName;
    }
    public int getLectureId() {
        return lectureId;
    }
    public void setLectureId(int lectureId) {
        this.lectureId = lectureId;
    }
    public String getLectureName() {
        return lectureName;
    }
    public void setLectureName(String lectureName) {
        this.lectureName = lectureName;
    }
    @Override
    public String toString() {
        return "Lecture [lectureId=" + lectureId + ", lectureName=" + lectureName + "]";
    }

}

Course.java

package com.learnfromexamples.serialization.customserialization;

public class Course{

    private int courseId;
    private String courseName;
    private double courseCost;
    private Lecture    staffTaken;
    public Course(int courseId, String courseName, double courseCost,Lecture lecture) {
        System.out.println("Course Constructor...");
        this.courseId = courseId;
        this.courseName = courseName;
        this.courseCost = courseCost;
        this.staffTaken = lecture;
    }
    
    public int getCourseId() {
        return courseId;
    }
    public void setCourseId(int courseId) {
        this.courseId = courseId;
    }
    public String getCourseName() {
        return courseName;
    }
    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }
    public double getCourseCost() {
        return courseCost;
    }
    public void setCourseCost(double courseCost) {
        this.courseCost = courseCost;
    }

    public Lecture getStaffTaken() {
        return staffTaken;
    }

    public void setStaffTaken(Lecture staffTaken) {
        this.staffTaken = staffTaken;
    }

    @Override
    public String toString() {
        return "Course [courseId=" + courseId + ", courseName=" + courseName + ", courseCost=" + courseCost
                + ", staffTaken=" + staffTaken + "]";
    }

    
}

Student.java

package com.learnfromexamples.serialization.customserialization;

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

public class Student implements Serializable{
    
    private int studentRollNo;
    private String studentName;
    private String studentAddress;
    transient private Course course;
    transient private Department department;
    public Student(int studentRollNo, String studentName, String studentAddress, Course course, Department department) {
        System.out.println("Student Constructor...");
        this.studentRollNo = studentRollNo;
        this.studentName = studentName;
        this.studentAddress = studentAddress;
        this.course = course;
        this.department = department;
    }

    public int getStudentRollNo() {
        return studentRollNo;
    }

    public void setStudentRollNo(int studentRollNo) {
        this.studentRollNo = studentRollNo;
    }

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public String getStudentAddress() {
        return studentAddress;
    }

    public void setStudentAddress(String studentAddress) {
        this.studentAddress = studentAddress;
    }

    
    public Course getCourse() {
        return course;
    }

    public void setCourse(Course course) {
        this.course = course;
    }

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    @Override
    public String toString() {
        return "Student [studentRollNo=" + studentRollNo + ", studentName=" + studentName + ", studentAddress="
                + studentAddress + ", course=" + course + ", department=" + department + "]";
    }

    private void writeObject(ObjectOutputStream objectOutputStream) throws IOException{
        System.out.println("Custom Serialization starts");
            objectOutputStream.defaultWriteObject();
            
            objectOutputStream.writeInt(course.getStaffTaken().getLectureId());
            objectOutputStream.writeObject(course.getStaffTaken().getLectureName());
            
            objectOutputStream.writeInt(course.getCourseId());
            objectOutputStream.writeObject(course.getCourseName());
            objectOutputStream.writeDouble(course.getCourseCost());
            //objectOutputStream.writeObject(course.getStaffTaken());
            
            objectOutputStream.writeInt(department.getDeptNo());
            objectOutputStream.writeObject(department.getDeptName());
        
        System.out.println("Custom Serialization ends");
    }
    
    private void readObject(ObjectInputStream objectinputStream) throws IOException, ClassNotFoundException {
        System.out.println("Custom De Serialization starts");
        objectinputStream.defaultReadObject();
        int lectureId = objectinputStream.readInt();
        String lectureName = (String)objectinputStream.readObject();
        
        
        int courseId = objectinputStream.readInt();
        String courseName =  (String)objectinputStream.readObject();
        double courseCost = objectinputStream.readDouble();
        course = new Course(courseId, 
                courseName, courseCost, 
                new Lecture(lectureId,lectureName));
        
        int deptNo =  objectinputStream.readInt();
        String deptName =  (String)objectinputStream.readObject();
        department = new Department(deptNo, deptName);
        System.out.println("Custom De Serialization starts");
    }
}

StudentSerializationImplementation.java

package com.learnfromexamples.serialization.customserialization;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class StudentSerializationImplementation {

    public static void main(String[] args) throws IOException {
        Lecture lecture = new Lecture(1001, "Sripathy");
        Course course = new Course(1, "Java Serialization", 500, lecture);
        Department department = new Department(101,"CS");
        Student student = new Student(25, "Sridhar", "Chennai", course,department);
        
        System.out.println(student);
        FileOutputStream fileOutputStream;
        try {
            fileOutputStream = new FileOutputStream("student.ser");
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
            System.out.println("Serialization starts");
            objectOutputStream.writeObject(student);
            System.out.println("Serialization ends");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Output

Lecture Constructor...
Course Constructor...
Department Constructor...
Student Constructor...
Student [studentRollNo=25, studentName=Sridhar, studentAddress=Chennai, course=Course [courseId=1, courseName=Java Serialization, courseCost=500.0, staffTaken=Lecture [lectureId=1001, lectureName=Sripathy]], department=Department [deptNo=101, deptName=CS]]
Serialization starts
Custom Serialization starts
Custom Serialization ends
Serialization ends
package com.learnfromexamples.serialization.customserialization;

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

public class StudentDeSerializationImplementation {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileInputStream fileInputStream = new FileInputStream("student.ser");
        ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
        System.out.println("De Serialization starts");
        Student student = (Student)inputStream.readObject();
        System.out.println("De Serialization Ends");
        System.out.println("---------------------");
        System.out.println("De-Serialized Object");
        System.out.println(student);
    }
}

Output

De Serialization starts
Custom De Serialization starts
Lecture Constructor...
Course Constructor...
Department Constructor...
Custom De Serialization starts
De Serialization Ends
---------------------
De-Serialized Object
Student [studentRollNo=25, studentName=Sridhar, studentAddress=Chennai, course=Course [courseId=1, courseName=Java Serialization, courseCost=500.0, staffTaken=Lecture [lectureId=1001, lectureName=Sripathy]], department=Department [deptNo=101, deptName=CS]]

Java Serialization – Good to Know 4

As part of Customized serialization in writeObject method, first we have to call defaultWriteObject method followed by state of other variables which we wish to add. Also in readObject method, first we should call defaultReadObject method followed by the objects which we have added earlier. Also during deserialization we have to read in the same order which we have added.

Java Serialization – Good to Know 5

Even though we manually add the state of an object, we have to manually add each variable as part of serialization. We shouldn’t add entire Course or Department or Lecture object state directly. We have to manually add each variable of those objects. Also we have to manually read all the variables in the same order we have added.

Java Serialization – Good to Know 6

During custom deserialization, we have noticed that constructor of Lecture, Department, Course class has been called. Because here we are reading the state of variables and recreating the object, not reconstructing the existing objects.

In this tutorial we have seen only the basics of Java Serialization, we have lots to see about Java Serialization which we will discuss in the next tutorial.

If you have any questions on this post please comment it. Also if you like this post, please share it with your friends by clicking on the Social media buttons and also provide your feedback in the comment box.