Java Serialization Using Serializable and Externalizable

AbdulMazed's Avatar author of Java Serialization Using Serializable and Externalizable
This is an article on Java Serialization Using Serializable and Externalizable in Java.
Rated 5.00 By 1 users
Before we understand what Java Serialization is, first we need to understand what serialization means? In computer science, in the context of data storage, serialization is the process of translating data structures or object state into a format that can be stored and reconstructed later in the same or another computer environment. This process of serializing an object is also called marshalling an object. The opposite operation, extracting a data structure from a series of bytes, is de-serialization (which is also called un-marshalling).

Java supports serialization to stream an object to a sequence of byte, so that it can be transmitted over the network, can be stored in a persistent storage and rebuild these objects from this stream of bytes. To make a Java object serializable, its class or any of its super-classes implements either the java.io.Serializable interface or its sub-interface, java.io.Externalizable. java.io.Serializable interface is only a marker interface which tells the Java platform that the object is serializable. Serialization and de-serialization is JVM independent meaning an object can be serialized on one platform and de-serialized on a different platform.

If an object’s property is declared as transient then its value will not be serialized during object serialization. Certain system-level classes such as Thread, OutputStream and its subclasses, and Socket are not serializable. If a serializable class contains such objects, it must mark as transient.

For example, the java.awt.Button class implements the Serializable interface, so you can serialize a java.awt.Button object and store that serialized state in a file. Later, you can read back the serialized state and deserialize into a java.awt.Button object.
ObjectOutputStream is used to serialize and ObjectOutputStream is used to de-serialize an object . writeObject(ObjectOutputStream oos) to write object into stream and readObject() method is to read object from stream.

Example of Java Serialization and de-serialization



If a class objects to be serialized; the class must implement the serializable interface. Here is Employee class which implements serializable interface.

Employee.java
Code:
package com.amazed.serialization ;
import java.io.Serializable;
public class Employee implements Serializable {
     
    private String name;
    private int id;
	private String department;
    transient private int salary;
     
    @Override
    public String toString(){
        return "Employee {name = " + name + ", id = " + id + ", department = " + department + ", salary = " + salary + "}";
    }
     
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getDepartment() {
        return department;
    }
	
   public void setDepartment(String department) {
        this.department = department;
    }
	
    public int getSalary() {
        return salary;
    }
 
    public void setSalary(int salary) {
        this.salary = salary;
    }
}
Note: salary is declared as transient so it will not be serialized.

Now serialize the employee object into a file

SerializeEmployee.java
Code:
package com.amazed.serialization ;
import java.io.*;
public class SerializeEmployee {

   public static void main(String [] args){
      // create an employee object 
      Employee emp = new Employee();
	  emp.setName("Mazed") ;
	  emp.setId(100) ;
	  emp.setDepartment("IT") ;
	  emp.setSalary(10000) ;
      
      try {
         FileOutputStream targetFile = new FileOutputStream("employee.ser");
         ObjectOutputStream objOS = new ObjectOutputStream(targetFile);
         objOS.writeObject(emp);
         objOS.close();
         targetFile.close();
         System.out.printf("Employee data has been saved");
      } catch(IOException ioe) {
          ioe.printStackTrace();
      }
   }
}
Output of SerializeEmployee code



Now to read the object back from the file, we need to de-serialize the object. The below program will read the object from file.

DeserializeEmployee.java
Code:
package com.amazed.serialization ;
import java.io.*;
public class DeserializeEmployee {
   public static void main(String [] args){
   
      Employee emp = null;
	  
      try {
         FileInputStream sourceFile = new FileInputStream("employee.ser");
         ObjectInputStream objIs = new ObjectInputStream(sourceFile);
         emp = (Employee) objIs.readObject(); // read object cast to Employee object. If JVM cannot locate or find the 
		                                      // Employee class then ClassNotFoundException will be thrown
         objIs.close();
         sourceFile.close();
      } catch(IOException ioe) {
         ioe.printStackTrace();
         return;
      } catch(ClassNotFoundException c) {
         System.out.println("Employee class not found");
         c.printStackTrace();
         return;
      }
	  
	  // Now  retrieve the employee details after de-serializing the employee object
      System.out.println("Employee details...");
      System.out.println("Name: " + emp.getName());
      System.out.println("ID: " + emp.getId());
      System.out.println("Department: " + emp.getDepartment());
      System.out.println("Salary: " + emp.getSalary());
    }
}
Output of DeserializeEmployee code



Here salary is showing 0 because value was not persisted during serialization as the field has declared as transient.

Use Externalizable Interface for serialization



When a class implements Externalizable interface, it is the responsibility of the class itself to save and restore the contents of its instances. The writeExternal() and readExternal() methods of the Externalizable interface are implemented by a class to give the class complete control over the format and contents of the stream for an object and its supertypes. These methods must explicitly coordinate with the supertype to save its state. These methods supersede customized implementations of writeObject() and readObject() methods.

If the object supports Externalizable, the writeExternal() method is called. If the object does not support Externalizable and does implement Serializable, the object is saved using ObjectOutputStream and writeObject() writes the objects into stream.

When an Externalizable object is reconstructed, an instance is created using the public no-arg constructor, then the readExternal method called. Serializable objects are restored by reading them from an ObjectInputStream.

Below example demonstrate the implementation of Externalizable interface

Contact.java
Code:
package com.amazed.serialization ;
 
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
 
public class Contact implements Externalizable {
 
    private String name ;
    private String gender ;
	private String address ;
	
    public Contact () {
	}
		
    @Override
    public void writeExternal(ObjectOutput oo) throws IOException {        
        oo.writeObject("Custom : " + name);
        oo.writeObject("Custom : " + gender);
		oo.writeObject("Custom : " + address);		
    }
 
    @Override
    public void readExternal(ObjectInput oin) throws IOException,
            ClassNotFoundException {
        
        name = (String) oin.readObject();
        if(!name.startsWith("Custom")) throw new IOException("Not a valid data");
        name = name.substring(6);
		
        gender = (String) oin.readObject();
        if(!gender.startsWith("Custom")) throw new IOException("Not a valid data");
        gender = gender.substring(6);
		
		address = (String) oin.readObject();
        if(!address.startsWith("Custom")) throw new IOException("Not a valid data");
        address = address.substring(6);
    }
 
    @Override
    public String toString(){
        return "Contact { Name" + name + ", Gender" + gender + ", Address" + address + "}";
    }
    
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getGender() {
        return gender;
    }
 
    public void setGender(String gender) {
        this.gender = gender;
    }
	
   public String getAddress() {
        return address;
    }
	
    public void setAddress(String address) {
        this.address = address;
    }
}
ExternalizationDemo.java
Code:
package com.amazed.serialization ;
 
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
 
public class ExternalizationDemo {
 
    public static void main(String[] args) {
         
        String fileName = "contact.ex";
        Contact contact = new Contact();
        contact.setName("Mazed");
        contact.setGender("Male");
		contact.setAddress("Kolkata, West Bengal, India");
         
        try {
            FileOutputStream fos = new FileOutputStream(fileName);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(contact);
            oos.close();
        } catch (IOException e) {            
            e.printStackTrace();
        }
         
        FileInputStream fis;
        try {
            fis = new FileInputStream(fileName);
            ObjectInputStream ois = new ObjectInputStream(fis);
            Contact readContact = (Contact)ois.readObject();
            ois.close();
			// now print contact
            System.out.println("Contact read = " + readContact);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }    
    }
}
Output of ExternalizationDemo code



Comparison of Serializable and Externalizable



Serializable
  • Methods - No method declared. Marker Interface
  • Process responsibility - Default serialization process. JVM’s responsibility
  • Performance - Programmer does not have control to improve the performance.

Externalizable
  • Methods - Two methods declared in it writeExternal() and readExternal()
  • Process responsibility - Custom defined; programmer’s own responsibility to define serialization mechanism
  • Performance - Performance can be improved as programmer’s has full control over serialization process.

References:


  1. http://en.wikipedia.org/wiki/Serialization
shabbir like this