Friday 26 August 2016

Is Serialization saves super class fields?

There are two cases to consider here.
a.   What if super class implements Serializable interface
b.   What if super class don’t implement Serializable interface

What if super class implements Serializable interface
If super class is serializable, then Serialization stores all the non-transient instance fields available to sub class.


Person.java
import java.io.Serializable;

public class Person implements Serializable {
 private static final long serialVersionUID = 1234L;

 protected  String firstName;
 protected String lastName;

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 Person(String firstName, String lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
 }

}


Employee.java
import java.io.Serializable;

public class Employee extends Person implements Serializable {
 private static final long serialVersionUID = 1234L;

 private int id;

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 @Override
 public String toString() {
  return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + "]";
 }

 public Employee(int id, String firstName, String lastName) {
  super(firstName, lastName);
  this.id = id;
 }

}


As you see Employee class, it extends Person class which is serializable. So When you serialize Employee object, it also store the variables firstName and lastName defined in Person class.

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

public class Test {
 private static ObjectOutputStream out;
 private static ObjectInputStream in;

 public static void main(String args[]) throws IOException, ClassNotFoundException {
  /* Serialize object */
  FileOutputStream fos = new FileOutputStream("ser.out");
  out = new ObjectOutputStream(fos);
  Employee emp = new Employee(123, "Hari Krishna", "Gurram");
  out.writeObject(emp);

  /* Deserialize object */
  FileInputStream fis = new FileInputStream("ser.out");
  in = new ObjectInputStream(fis);
  Employee emp1 = (Employee) in.readObject();

  System.out.println(emp1);

 }
}

Output
Employee [id=123, firstName=Hari Krishna, lastName=Gurram]

What if super class is not serializable?
As per Javadoc, during deserialization, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class. A no-arg constructor must be accessible to the subclass that is serializable.

Person.java
public class Person {

 protected String firstName;
 protected String lastName;

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

}

Employee.java
import java.io.Serializable;

public class Employee extends Person implements Serializable {
 private static final long serialVersionUID = 1234L;

 private int id;

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 @Override
 public String toString() {
  return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + "]";
 }

 public Employee(int id, String firstName, String lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.id = id;
 }

}

As you see, Person.java class is not implementing Serializable interface. When you run perform deserialization on Employee object, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class. Since Person class don’t has any default constructor defined, the fields firstName and lastName are initialized to null.

Re run Test.java with the updated Person and Employee classes, you will get following output.

Output
Employee [id=123, firstName=null, lastName=null]


As I said, during deserialization, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class. To confirm this update Person class by adding following constructor.

public Person(){
         this.firstName = "no_name";
         this.lastName = "no_name";
}

Following is the updated Person class.
public class Person {

 protected String firstName;
 protected String lastName;

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 public Person() {
  this.firstName = "no_name";
  this.lastName = "no_name";
 }

}

Re run Test.java, you can able to see following output.

Employee [id=123, firstName=no_name, lastName=no_name]


You may like







No comments:

Post a Comment