In this article, we will discuss Order of Serialization and De-Serialization and also we will cover below programs
- Why it is important to know order of serialization
- What happens, if de-serialize in different order than serialization order
- What is the readymade solution available from Java to overcome this situation, if we don’t know the order of serialization
1. Serialization process:
- During serialization process i.e.; saving state of an Object to File, only instance variables will be participated and persisted to file storage or some other storage via network capability
2. De-Serialization process:
- During de-serialization process, Object’s state will be restored back from file storage
3. Order of Serialization and De-Serialization :
- Create 3 POJO classes namely Customer, Employee and Student and all should implementing java.io.Serializable interface
- Any class said to be serializable, if it implements java.io.Serializable interface
- Otherwise, NotSerializableException will be thrown at run time, although program compiles successfully
- All POJO’s has 2 instance variables & 2-arg parameterized constructor and overrides toString() method to print values in desired format
Customer.java
package in.bench.resources.serialization;
import java.io.Serializable;
class Customer implements Serializable {
// member variables for Customer
int customerId;
String customerName;
// 2-arg parameterized constructor for Customer
public Customer(int customerId, String customerName) {
this.customerId = customerId;
this.customerName = customerName;
}
@Override
public String toString() {
return "Customer ["
+ "customerId=" + customerId
+ ", customerName=" + customerName
+ "]";
}
}
Employee.java
package in.bench.resources.serialization;
import java.io.Serializable;
class Employee implements Serializable {
// member variables for Employee
int employeeId;
String employeeName;
// 2-arg parameterized constructor for Employee
public Employee(int employeeId, String employeeName) {
this.employeeId = employeeId;
this.employeeName = employeeName;
}
@Override
public String toString() {
return "Employee ["
+ "employeeId=" + employeeId
+ ", employeeName=" + employeeName
+ "]";
}
}
Student.java
package in.bench.resources.serialization;
import java.io.Serializable;
class Student implements Serializable {
// member variables for Student
int studentId;
String studentName;
// 2-arg parameterized constructor for Student
public Student(int studentId, String studentName) {
this.studentId = studentId;
this.studentName = studentName;
}
@Override
public String toString() {
return "Student ["
+ "studentId=" + studentId
+ ", studentName=" + studentName
+ "]";
}
}
4. Serialization and De-serialization :
- As we are ready with POJOs, we will begin with our serialization and de-serialization for 3 different cases
- To Serialize any Object, we can use ObjectOutputStream & FileOutputStream to write/save tofile in binary format
- To De-Serialize any Object, we can use ObjectInputStream & FileInputStream to read/restore from file (which is in binary format) into Java heap memory
4.1 When order of serialization is known, we can de-serialize in same order
- Here, we know serialization order
- so it becomes very easy for us to do de-serialization
OrderOfSerializationDeSerialization.java
package in.bench.resources.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 OrderOfSerializationDeSerialization {
public static void main(String[] args) {
Customer customer = new Customer(101, "Jeremy Krist");
Employee employee = new Employee(111, "Mike Gentry");
Student student = new Student(121, "Azeem Sayed");
// creating output stream variables
FileOutputStream fos = null;
ObjectOutputStream oos = null;
// creating input stream variables
FileInputStream fis = null;
ObjectInputStream ois = null;
// creating customer object reference
// to hold values after de-serialization
Customer deSerializeCustomer = null;
Employee deSerializeEmployee = null;
Student deSerializeStudent = null;
try {
// for writing or saving binary data
fos = new FileOutputStream("OrderOfObjects.ser");
// converting java-object to binary-format
oos = new ObjectOutputStream(fos);
// writing or saving customer object's value to stream
oos.writeObject(customer);
oos.writeObject(employee);
oos.writeObject(student);
oos.flush();
oos.close();
System.out.println("Serialization: All objects "
+ "saved to OrderOfObjects.ser file\n");
// reading binary data
fis = new FileInputStream("OrderOfObjects.ser");
// converting binary-data to java-object
ois = new ObjectInputStream(fis);
// reading object's value and casting to respective class
deSerializeCustomer = (Customer) ois.readObject();
deSerializeEmployee = (Employee) ois.readObject();
deSerializeStudent = (Student) ois.readObject();
ois.close();
System.out.println("De-Serialization: All objects "
+ "de-serialized from OrderOfObjects.ser file\n");
}
catch (FileNotFoundException fnfex) {
fnfex.printStackTrace();
}
catch (IOException ioex) {
ioex.printStackTrace();
}
catch (ClassNotFoundException ccex) {
ccex.printStackTrace();
}
// printing customer object to console using toString() method
System.out.println("Printing values "
+ "from de-serialized object... \n");
System.out.println(deSerializeCustomer);
System.out.println(deSerializeEmployee);
System.out.println(deSerializeStudent);
}
}
Output:
Serialization: All objects saved to OrderOfObjects.ser file
De-Serialization: All objects de-serialized from OrderOfObjects.ser file
Printing values from de-serialized object...
Customer [customerId=101, customerName=Jeremy Krist]
Employee [employeeId=111, employeeName=Mike Gentry]
Student [studentId=121, studentName=Azeem Sayed]
4.2 De-serialization is done in different than serialization order
- In this program, irrespective of whether we know serialization order or NOT, we will perform de-serialization in some random order
Let’s see what happens, if we change the de-serialization order, other than from serialization order
4.2.1 Serializing order
- Customer
- Employee
- Student
4.2.2 De-Serializing order
- Student
- Customer
- Employee
OrderOfSerializationDeSerialization.java
package in.bench.resources.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 OrderOfSerializationDeSerialization {
public static void main(String[] args) {
Customer customer = new Customer(101, "Jeremy Krist");
Employee employee = new Employee(111, "Mike Gentry");
Student student = new Student(121, "Azeem Sayed");
// creating output stream variables
FileOutputStream fos = null;
ObjectOutputStream oos = null;
// creating input stream variables
FileInputStream fis = null;
ObjectInputStream ois = null;
// creating customer object reference
// to hold values after de-serialization
Customer deSerializeCustomer = null;
Employee deSerializeEmployee = null;
Student deSerializeStudent = null;
try {
// for writing or saving binary data
fos = new FileOutputStream("OrderOfObjects.ser");
// converting java-object to binary-format
oos = new ObjectOutputStream(fos);
// writing or saving customer object's value to stream
oos.writeObject(customer);
oos.writeObject(employee);
oos.writeObject(student);
oos.flush();
oos.close();
System.out.println("Serialization: All objects "
+ "saved to OrderOfObjects.ser file\n");
// reading binary data
fis = new FileInputStream("OrderOfObjects.ser");
// converting binary-data to java-object
ois = new ObjectInputStream(fis);
// reading object's value and casting to respective class
deSerializeStudent = (Student) ois.readObject();
deSerializeCustomer = (Customer) ois.readObject();
deSerializeEmployee = (Employee) ois.readObject();
ois.close();
System.out.println("De-Serialization: All objects "
+ "de-serialized from OrderOfObjects.ser file\n");
}
catch (FileNotFoundException fnfex) {
fnfex.printStackTrace();
}
catch (IOException ioex) {
ioex.printStackTrace();
}
catch (ClassNotFoundException ccex) {
ccex.printStackTrace();
}
// printing customer object to console using toString() method
System.out.println("Printing values"
+ " from de-serialized object... \n");
System.out.println(deSerializeCustomer);
System.out.println(deSerializeEmployee);
System.out.println(deSerializeStudent);
}
}
Output:
Serialization: All objects saved to OrderOfObjects.ser file
Exception in thread "main" java.lang.ClassCastException: in.bench.resources
.serialization.Customer cannot be cast to
in.bench.resources.serialization.Student
at in.bench.resources.serialization.OrderOfSerializationDeSerialization
.main(OrderOfSerializationDeSerialization.java:109)
Explanation:
- Here serialization order is Customer –> Employee –> Student
- But we are de-serializing in different order i.e.; Student –> Customer –> Employee
- So, while de-serializing 1st time when we read object from serialized file, it returns Customer object, as we serialized Customer object first
- But instead of type-casting to Customer object, we type-casted to Student object –> which results in throwing java.lang.ClassCastException
- To overcome this exception, we can use instanceOf operator
- Move to program 3 –> for much improved version using instanceOf operator
4.3 When order of serialization is unknown, how can we overcome this situation ?
- We can use instanceOf operator to check respective object first, iterating through while loop
- Later, we can assign it to correct class by type-casting
- Note: here, program will throw java.io.EOFException for condition checked inside parenthesis of while loop
- But we can catch this exception and take corrective action (like here, we can print “End of file message” to console)
OrderOfSerializationDeSerialization.java
package in.bench.resources.serialization;
import java.io.EOFException;
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 OrderOfSerializationDeSerialization {
public static void main(String[] args) throws IOException {
Customer customer = new Customer(101, "Jeremy Krist");
Employee employee = new Employee(111, "Mike Gentry");
Student student = new Student(121, "Azeem Sayed");
// creating output stream variables
FileOutputStream fos = null;
ObjectOutputStream oos = null;
// creating input stream variables
FileInputStream fis = null;
ObjectInputStream ois = null;
// creating customer object reference
// to hold values after de-serialization
Customer deSerializeCustomer = null;
Employee deSerializeEmployee = null;
Student deSerializeStudent = null;
try {
// for writing or saving binary data
fos = new FileOutputStream("OrderOfObjects.ser");
// converting java-object to binary-format
oos = new ObjectOutputStream(fos);
// writing or saving customer object's value to stream
oos.writeObject(customer);
oos.writeObject(employee);
oos.writeObject(student);
oos.flush();
oos.close();
System.out.println("Serialization: All objects "
+ "saved to OrderOfObjects.ser file\n");
// reading binary data
fis = new FileInputStream("OrderOfObjects.ser");
// converting binary-data to java-object
ois = new ObjectInputStream(fis);
// temp Object variable
Object object = null;
// iterating, reading & casting to respective class
while((object = ois.readObject()) != null){
if(object instanceof Customer)
deSerializeCustomer = (Customer) object;
else if(object instanceof Employee)
deSerializeEmployee = (Employee) object;
else if(object instanceof Student)
deSerializeStudent = (Student) object;
} // END of while loop
}
catch (EOFException eofex) {
// eofex.printStackTrace();
System.out.println("De-Serialization: All objects "
+ "de-serialized from OrderOfObjects.ser file\n");
System.out.println("End of file reached...\n");
}
catch (FileNotFoundException fnfex) {
fnfex.printStackTrace();
}
catch (IOException ioex) {
ioex.printStackTrace();
}
catch (ClassNotFoundException ccex) {
ccex.printStackTrace();
}
finally {
ois.close(); // closing stream
}
// printing customer object to console using toString() method
System.out.println("Printing values "
+ "from de-serialized object... \n");
System.out.println(deSerializeCustomer);
System.out.println(deSerializeEmployee);
System.out.println(deSerializeStudent);
}
}
Output:
Serialization: All objects saved to OrderOfObjects.ser file
De-Serialization: All objects de-serialized from OrderOfObjects.ser file
End of file reached...
Printing values from de-serialized object...
Customer [customerId=101, customerName=Jeremy Krist]
Employee [employeeId=111, employeeName=Mike Gentry]
Student [studentId=121, studentName=Azeem Sayed]
5. Important points about Serialization Order:
- Rule 1: all classes that need to be serialized must implement java.io.Serializable interface
- Order of Serialization is very important to know, because we need to follow the same order while de-serializing objects
- If Order of Serialization is unknown, then it may throw java.lang.ClassCastException
- To overcome ClassCastException, we can 1st check type of object using instanceOf operator and then assign it to proper class after doing necessary type-casting
- Exception: iterating through while loop may throw EOFException, we need catch this exception and handle it properly
Related Articles:
- Java – Serialization and De-Serialization Tutorial Index
- Java – Introduction to Serialization and De-Serialization
- Java – Serializable interface
- Java – Transient keyword with Serialization
- Java – Transient keyword with static variable in Serialization
- Java – Transient keyword with final variable in Serialization
- Java – Serializing a variable with transient modifier or keyword
- Java – Order of Serialization and De-Serialization
- Java – Serialization with Aggregation
- Java – Serialization with Inheritance
- Java – Externalization in detail
- Java – Serializable v/s Externalizable
- Java – Importance of SerialVersionUID in Serialization
- Java – Singleton Design pattern with Serialization
- Java – How to construct a singleton class in a multi-threaded environment ?
- Java – Singleton design pattern, restricting Object creation by overriding readResolve() method
- Java – How to stop Serialization ?
- Java – How to serialize and de-serialize ArrayList ?
- Java – Interview question & answers on Serialization and Externalization
References:
- https://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
- https://docs.oracle.com/javase/7/docs/platform/serialization/spec/serial-arch.html
- https://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html
- https://docs.oracle.com/javase/7/docs/api/java/io/ObjectInputStream.html
- https://docs.oracle.com/javase/7/docs/api/java/io/FileOutputStream.html
- https://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html
- http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.3
Happy Coding !!
Happy Learning !!