Externalization in Java | Methods, Example

Externalization in Java is a process that improves the performance of serialization and deserialization mechanisms by complete control over what data fields are serialized and deserialized.

In other simple words, externalization is used to customize serialization and deserialization processes. It provides complete control over the serialization and deserialization tasks.

Java supports the externalization process by the externalizable interface.

Implementing the Externalizable interface by a class provides more control in reading and writing objects from/to a stream.

The main advantage of externalization over the serialization process is that everything is taken care of by the programmer. JVM has no control over it. The complete serialization control goes to the application.

Based on our requirements, we can serialize either the whole data field or a piece of the data field using the externalizable interface which can help to improve the performance of the application.

In the serialization process, JVM is taken care of everything. That is, JVM takes care of details of reading/writing Serializable objects from/to a stream.

The programmer has no control over them. We can not store a piece of data that may create performance problems. To overcome this problem, Java introduced an externalization mechanism.

Externalizable Interface in Java


Externalizable interface that extends Serializable interface. The general syntax to declare an Externalizable interface in Java is as follows:

public interface Externalizable
       extends Serializable

A class must implement the Externalizable interface for complete control over the serialization process. To externalize objects, only the state of the object’s class is automatically stored by the stream. The class that implements Externalizable interface is responsible for writing and reading its contents or data.

The complete syntax of the Externalizable interface that extends Serializable interface is as follows below:

package java.io;
public interface Externalizable extends Serializable
{
   public void writeExternal(ObjectOutput out) throws IOException;
   public void readExternal(ObjectInput in) throws IOException, java.lang.ClassNotFoundException;
}

A writeExternal() method must be implemented to store the state (field) of objects in a class that implements Externalizable interface.


Similarly, readExternal() method must be implemented to read data written by writeExternal() method from the stream and restore the state of objects.

Methods of Externalizable Interface in Java


Externalizable interface is not a marker interface like Serializable interface. So, it provides two methods that are as follows:

1. void readExternal(ObjectInput inStream): The readExternal() method restores the calling object’s contents by calling various methods on the specified ObjectInput in.

In other simple words, we call readExternal() method when we want to read an object’s fields from a stream. We need to write logic to read an object’s fields inside the readExternal() method.

The general syntax to declare readExternal() method with the specified object input stream is as follows:

public void readExternal(ObjectInput inStream) throws IOException, ClassNotFoundException 
{
   // Here, write the logic to read an object's fields from the stream.
}

In this method, inStream is the byte stream from which the object is to be read. ObjectInput is a sub-interface of DataInput and is implemented by ObjectInputStream.

We can use readBoolean(), readByte(), readInt(), readLong() methods for primitive data types and readObject() method for String, Arrays, or any of the custom classes.

The readExternal() method throws IOException when an I/O error occurs. If the class of object being restored does not find, ClassNotException will be thrown.


2. void writeExternal(ObjectOutput outStream): The writeExternal() method saves the calling object’s contents by calling various methods on the specified ObjectOutput outStream.

In simple words, writeExternal() method is used when we want to write an object’s fields to a stream. We need to write the logic to write data fields inside writeExternal() method.

The general syntax to declare writeExternal() method with the specified object output stream is as follows:

public void writeExternal(ObjectOutput outStream) throws IOException
{
    // Here, write the logic to write object fields to a stream.
}

outStream is the byte stream to which the object is to be written. ObjectOutput is a sub-interface of DataOutput and is implemented by ObjectOutputStream.


We can use writeBoolean(), writeByte(), writeInt(), writeLong() methods for primitive data types and writeObject() method for strings, arrays, and custom classes.

This method can throw an IOException when an I/O error occurs.

Java Externalization Example Programs


1. Let’s take a simple example program where we will understand step by step how to serialize and deserialize Externalizable object fields. Look at the source code to understand better.

Program source code 1: 

package javaProgram;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

// A Person class that implements Externalizable interface. 
public class Person implements Externalizable 
{
   String name;
   int age;

@Override
public void writeExternal(ObjectOutput outStream) throws IOException
{
// Writing name and age to the stream.	
	outStream.writeObject(name);
	outStream.writeInt(age);
}
@Override
public void readExternal(ObjectInput inStream) throws ClassNotFoundException, IOException
{
// Reading name and age in the same order in which they were written. 	
	name = (String)inStream.readObject();
	age = inStream.readInt();
  }
}

In this source code, Java will pass the reference of the object output stream and object input stream to the writeExternal() and readExternal() methods of the Person class respectively.

In the writeExternal() method, we write the name and age fields to the object output stream. The writeObject() and writeInt() methods are used to write Externalizable object fields such as name and age to the object output stream.

In the readExternal() method, we read the Externalizable object fields such as name and age from the stream and set them in the name and age instance variables.


Let’s create a class named SerializePerson where we will serialize total object fields of the Person class that implements Externalizable interface.

package javaProgram;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class SerializePerson {
public static void main(String[] args) throws IOException 
{
// Create an object of Person class.	
    Person p = new Person();
      p.name = "Shubh";
      p.age = 32;

// Create File object.
     File file = new File("D:\\objfile.txt"); 
     FileOutputStream fos = new FileOutputStream(file);
     ObjectOutputStream oos = new ObjectOutputStream(fos);

// Write or serialize objects to object output stream. 
      oos.writeObject(p);
      oos.flush();

     System.out.println("Data has been written successfully...");
// Print the output path of the file.
     System.out.println("Data are written to: " +file.getAbsolutePath());
 }
}
Output:
            Data has been written successfully...
            Data are written to: D:\objfile.txt

Let’s create a class DeserializePerson where we will deserialize total object fields of the Person class that implements Externalizable interface.

package javaProgram;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class DeserializePerson {
public static void main(String[] args) throws IOException, ClassNotFoundException 
{
// Create a input file object. 	
    File file = new File("D:\\objfile.txt");	
    FileInputStream fis = new FileInputStream(file);
    ObjectInputStream ois = new ObjectInputStream(fis);

// Deserialize or read objects of Person class.  
     Person p = (Person)ois.readObject();

// Displaying objects that are read from file. 
     System.out.println("Name: " +p.name);
     System.out.println("Age: " +p.age);

// Print the input path of the file.
     System.out.println("Data are read from " +file.getAbsolutePath());
 }
}
Output:
          Name: Shubh
          Age: 32
          Data are read from D:\objfile.txt

Note:

a) In the serialization process, JVM first checks for Externalizable interface. If objects support Externalizable interface, JVM serializes objects using writeExternal() method.

If objects do not support Externalizable but implement Serializable, objects are stored using ObjectOutputStream.

b) For serializable objects, JVM serializes the only instance variables that are not declared with the transient keyword.

c) For externalizable objects, we have full control over what pieces of data have to serialize and what to not serialize.


2. Let’s take another example program where we will serialize a piece of data fields in the writeExternal() method and deserialize a piece of data fields in the readExternal() method using an Externalizable interface.

Program source code 2:

package javaProgram;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

public class Employee implements Externalizable {
 String name;
 int id;
 double salary;

Employee(String name, int id, double salary) {
  this.name = name;
  this.id = id;
  this.salary = salary;
 }
@Override
public void writeExternal(ObjectOutput outStream) throws IOException
{
// Serializing only id and salary. 	
	outStream.writeInt(id);
	outStream.writeDouble(salary);
}
@Override
public void readExternal(ObjectInput inStream) throws ClassNotFoundException, IOException
{
// Order of reads must be the same as the order of writes.
	id = inStream.readInt(); 
	salary = inStream.readDouble();
 }
}

Let’s create a program where we will serialize an Employee object that implements an Externalizable interface.

package javaProgram;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class SerializeEmployee {
public static void main(String[ ] args) throws IOException 
{
// Create an object of class Employee.
    Employee emp = new Employee("John", 124353, 200000.65 );	

   File file = new File("D:\\objfile.txt");
   FileOutputStream fos = new FileOutputStream(file);
   ObjectOutputStream oos = new ObjectOutputStream(fos);
 
   emp.writeExternal(oos); // Externalizing employee.
   System.out.println("An employee is externalized into objfile.txt file.");
 
// Display the serialized data on the Standard Output.
    System.out.println("Data written into file:");
    System.out.println("Employee's id: " +emp.id);
    System.out.println("Employee's salary: "+"Rs " +emp.salary);
 
// Print output path. 
    System.out.println("Data are written to " +file.getAbsolutePath());
  }
}
Output:
         An employee is externalized into objfile.txt file.
         Data written into file:
         Employee's id: 124353
         Employee's salary: Rs 200000.65
         Data are written to D:\objfile.txt

As you can observe in this program, we have serialized only two data fields id and salary. Thus, we have control over the serialization.


Let’s create a program where we will deserialize an Employee object that implements an Externalizable interface.

package javaProgram;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class DeserializeEmployee {
public static void main(String[ ] args) throws IOException, ClassNotFoundException 
{
   File file = new File("D:\\objfile.txt");
   FileInputStream fis = new FileInputStream(file);
   ObjectInputStream ois = new ObjectInputStream(fis);

// Deserializing or reading one object.
    Employee emp = (Employee)ois.readObject();

// Displaying data (objects) that are read.
    System.out.println("Employee's id: " +emp.id);
    System.out.println("Employee's salary: " +emp.salary);

// Print input path.
    System.out.println("Data are read from " +file.getAbsolutePath());
   }
}
Output:
           Employee's id: 124353
           Employee's salary: Rs 200000.65
           Data are read from D:\objfile.txt

Difference between Serializable and Externalizable in Java


The difference between serializable and externalizable in java are as follows:

1. Serializable is a marker interface whereas, Externalizable is not a marker interface. It provides two methods: writeExternal() and readExternal().

2. In the case of Serializable, default serialization process is used. While, in the case of Externalization, custom serialization process is used that is implemented by the application.

3. In the serialization process, everything is taken care of by JVM and the programmer doesn’t have any control. While in the case of externalization process, everything is taken care of by the programmer and JVM doesn’t have any control.

4. Externalizable interface is generally used when we want to store the output data in custom format that is different from java default serialization format like csv, database, flat file, XML, etc.

5. In externalization process, readExternal() and writeExternal() methods are used to perform serialization.

6. Externalizable interface can improve the performance of serialization process if used correctly.


Hope that this tutorial has covered almost all the important points related to Externalization in Java with example programs. I hope that you will have understood the basic concepts of the externalization mechanism.

Thanks for reading!!!