The Externalizable Interface

Before you start exploring Externalization in Java, I would recommend you to gather some knowledge of Serialization in Java because Externalizable is an alternative to Serializable interface.


Externalizable interface allows you to customize how serialization is done. By implementing Externalizable you are controlling what gets serialized and what does not get serialized. Externalizable interface  extends Serializable interface and defines two methods to be overridden by the implementing class. 
  1. public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
  2. public void writeExternal(ObjectOutput out) throws IOException
Java class implementing Externalizable interface


package learn.java.serialization;


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


public class ExternalizableObject implements Externalizable{
   private String name;
   private  Date dob;
   private  int age;

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
name = (String) in.readObject();
age = in.readInt();
}
  @Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(name);
out.writeInt(age);
}
}



As you have noticed we are not serializing/de-serializing dob variable in the overriding methods. Now, in the following code snippet we will try to serialize/deserialize the above class instance.

public static void main(String[] args) {
   ExternalizableObject externalizableObject = new ExternalizableObject();
   externalizableObject.setAge(26);
   externalizableObject.setDob(new Date("20/09/1985"));
   externalizableObject.setName("dev");
   externalizeObject(externalizableObject);

   ExternalizableObject deserializedObj = deserializeExternalizeObject();
   System.out.println("Name: "+ deserializedObj .getName());
   System.out.println("DOB: "+ deserializedObj.getDob());
   System.out.println("Age: "+ deserializedObj.getAge());
}


private static void externalizeObject(ExternalizableObject obj){
   try {
      FileOutputStream fos = new FileOutputStream("C:/temp/test.txt");
      ObjectOutputStream out = new ObjectOutputStream(fos);
      out.writeObject( obj ); //writeExternal() of ExternalizableObject is invoked
      out.close();
   } catch (IOException e) {
      e.printStackTrace();
   }
}

private static ExternalizableObject deserializeExternalizeObject(){
   ExternalizableObject obj = null;


   try {
      FileInputStream fis = new FileInputStream(new File("C:/temp/test.txt"));
      ObjectInputStream in = new ObjectInputStream(fis);
      obj = (ExternalizableObject) in.readObject(); //readExternal() of ExternalizableObject is invoked
   } catch (Exception e) {
      e.printStackTrace();
   } 
   return externalizableObject;
}


During the Serialization process JVM first checks if the object implements Externizable interface, it invokes writeExternal method to serialize the object otherwise the object is serialized using ObjectOutputStream.


While reconstructing the serialized object, an instance is created first using the public no-arg constructor, then the readExternal method is called. If the class only have parameterized constructor(s) defined,  than java.io.InvalidClassException: no valid constructor Exception is thrown.


If a class inherits some class implementing the Externalizable interface, it must override writeExternal() and readExternal() methods to serialize or deserialize this class in order to correctly save and restore the object.

Comments

  1. Another useful point about serializable and externalizable interfaces is that when using Externalizable interface, we can create an intermmediate class which can provide default behavior of readXXX and writeXXX methods and hence avoid overriding these methods in all of the classes. Useful when in some of the classes you only want readXXX functionality and not writeXXX and vice versa.

    ReplyDelete

Post a Comment

Popular posts from this blog

Using Solr Spellchecker from Java

Importing / Indexing MySQL data into Solr

Custom PagingNavigator for SEO friendly URL