Externalizable interface with example

In this article, we will discuss externalizable interface with an example to save & restore an object in a customized way

Also, we will discuss advantage of using Externalizable over Serializable in detail

In next article we will cover important points while discussing difference between Externalizable and Serializable interfaces

 

Serializable interface:

Although, we have discussed serializable interface in detail in one of the previous article, here we will list out what are the various things that affects performance

  • While serializable implemented class does the necessary job of Serialization and de-serialization in saving & restoring object but in saves altogether all member variables of an object
  • This way, even if programmer requires only couple of member variables of an Object to be saved, Serializable doesn’t allow those kinds of flexibility
  • That is no flexibility saving & restoring partial object
  • It is time consuming in saving and restoring object during both serialization and de-serialization process
  • As JVM controls the complete serialization and de-serialization process and programmer has nothing to do with serializable interface
  • With transient modifier also, we can stop serializing original value but still that particular member variable get saved to file storage although with default value
  • Due to saving and restoring all member variables of an Object, even if programmer requires only couple of variables to saved and restored back, there is big performance hit

 

To overcome above listed performance issue with serializable, we have to serialize with externalizable interface which is sub-interface of Serializable interface

 

Advantage of Externalizable over Serializable:

  • Allows saving and restoring partial object i.e.; 2 or 3 member variables of an object out of total object
  • As programmer has to code/write the custom logic for serialization and de-serialization process, so write logic to save/restore those variables which is required
  • This way, there is performance boost relatively when comparing with serializable interface
  • Transient: variable is not required as programmer has the control over saving/restoring object and can easily ignore those variables whose value is secure or need to kept very secret
  • By saving and restoring partial object instead of total object, time consumption decreases (i.e.; time is saved in externalizable interface)

 

Externalizable interface

  • Externalizable interface is sub-interface of Serializable interface
  • Present in java.io package
  • Fully qualified class name is java.io.Externalizable
  • It has got 2 methods namely, writeExternal() and readExternal()
  • Method 1: with writeExternal(ObjectOutput out) method, programmer has to explicitly code/write logic for saving only those required variables to file storage
  • Method 2: with readExternal(ObjectInput in) method, programmer has to explicitly code/write logic for restoring object back from file storage
  • Note: class implementing externalizable interface should definitely consist of a public no-arg constructor, otherwise InvalidClassException is thrown
  • Design choice: This is the best suit; when partial object or few member variables of an object need to be serialized to file storage, otherwise still serializable interface is a good option for saving total object

 

Write complete method signature of 2 methods?

public void writeExternal(ObjectOutput out) throws IOException {}

public void readExternal(ObjectInput in) 
			throws IOException, ClassNotFoundException {}

 

Class to be serialized:

  • Below Customer class consists of 4 member variables, out of which 2 variables need to be serialized (and other variables are discarded)
  • In Externalization, programmer need to implement/override 2 methods for saving and restoring object
  • To partially serialize, we have to override 2 methods
    writeExternal(); –> for saving/writing in serialization process
    readExternal(); –> for restoring during de-serialization process

 

Serialization:

During serialization inside writeExternal(); method, programmer has to code/write custom logic to save/persist 2 member variables

 

De-Serialization:

During de-serialization inside readExternal(); method, programmer has to code/write custom logic to read 2 variable and then finally assigning to actual member variables

 

Customer.java

package in.bench.resources.externalization;

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

// class implementing Externalizable interface
class Customer implements Externalizable {

	// member variables for Customer
	int customerId;
	String customerName;
	int customerAge;
	String customerSSN;

	// default public no-arg constructor
	public Customer() {
		System.out.println("public no-arg constructor is must for "
				+ "Externalizable, "
				+ "while restoring object back from file storage");
	}

	// 4-arg parameterized constructor for Customer
	public Customer(int customerId, String customerName, 
			int customerAge, String customerSSN) {
		super();
		this.customerId = customerId;
		this.customerName = customerName;
		this.customerAge = customerAge;
		this.customerSSN = customerSSN;
	}

	@Override
	public void writeExternal(ObjectOutput out) throws IOException {

		// saving to file storage
		out.writeInt(customerId);
		out.writeObject(customerName);
	}

	@Override
	public void readExternal(ObjectInput in) 
			throws IOException, ClassNotFoundException {

		// restoring variables, as per order of serialization
		int tempCustId = in.readInt();
		String tempCustName = (String) in.readObject();

		// assigning restored values to member variables
		customerId = tempCustId;
		customerName = tempCustName;
	}

	// to print nicely - customer object
	@Override
	public String toString() {
		return "Customer [customerId=" + customerId 
				+ ", customerName=" + customerName 
				+ ", customerSSN=" + customerSSN
				+ ", customerAge=" + customerAge 
				+ "]";
	}
}

 

Serialization and De-serialization using Externalizable interface:

This program is the test class to write/save customer object to file storage and then restoring for reading customer object

  • 1st part explains, complete serialization process
  • 2nd explains, complete de-serialization process

Note: class that needs to be serialized is implementing Externalizable interface unlike Serializable interface in earlier examples

 

CustomerSerialization.java

package in.bench.resources.externalization;

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 CustomerSerialization {

	public static void main(String[] args) {

		// create an customer object using 4-arg constructor
		Customer serializeCustomer = 
				new Customer(102, "NK", 19, "SSN-78087");

		// 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;

		try {
			// for writing or saving binary data
			fos = new FileOutputStream("Customer.ser");

			// converting java-object to binary-format 
			oos = new ObjectOutputStream(fos);

			// writing or saving customer object's value to stream
			oos.writeObject(serializeCustomer);
			oos.flush();
			oos.close();

			System.out.println("Externalization: "
					+ "Customer object saved to Customer.ser file\n");

			// reading binary data
			fis = new FileInputStream("Customer.ser");

			// converting binary-data to java-object
			ois = new ObjectInputStream(fis);

			// reading object's value and casting to Customer class
			deSerializeCustomer = (Customer) ois.readObject();
			ois.close();

			System.out.println("Externalization: Customer object "
					+ "de-serialized from Customer.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 customer values from "
				+ "de-serialized object... \n" + deSerializeCustomer);
	}
}

Output:

Externalization: Customer object saved to Customer.ser file

public no-arg constructor is must for Externalizable, 
while restoring object back from file storage
Externalization: Customer object de-serialized from Customer.ser file

Printing customer values from de-serialized object... 
Customer [customerId=102, customerName=NK, customerSSN=null, customerAge=0]

 

Explanation:

  • Only two variables is persisted and restored back and other variables are discarded as it isn’t required
  • So, when we print customer object using overridden toString() method, only customer Id and customer Name is restored and other variables assigned to default values
  • Like, null for customer SSN number and 0 for customer age
  • Note: public no-arg constructor is very must while restoring object back from file storage
  • Otherwise, InvalidClassException is thrown

 

Exception scenario:

Let us tweak above example by removing public no-arg constructor and try to serialize & de-serialize customer object,

Output:

Externalization: Customer object saved to Customer.ser file

java.io.InvalidClassException: in.bench.resources.externalization
.Customer; no valid constructor
	at java.io.ObjectStreamClass$ExceptionInfo
.newInvalidClassException(ObjectStreamClass.java:150)
	at java.io.ObjectStreamClass
.checkDeserialize(ObjectStreamClass.java:790)
	at java.io.ObjectInputStream
.readOrdinaryObject(ObjectInputStream.java:1775)
	at java.io.ObjectInputStream
.readObject0(ObjectInputStream.java:1351)
	at java.io.ObjectInputStream
.readObject(ObjectInputStream.java:371)
	at in.bench.resources.externalization
.CustomerSerialization.main(CustomerSerialization.java:52)
Printing customer values from de-serialized object... 
null

 

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

 

Read Also:

 

Happy Coding !!
Happy Learning !!

Serializable v/s Externalizable
Serialization with Inheritance