0
Sponsored Links


Ad by Google
In this post we will learn about the java.io.Externalizable interface. Externalizable is an another way of serializing an object in java. To serialized an object your class or any of it's super classes must implements either the Serializable interface or it's sub interface called Externalizable. Before starting Externalizable you must have to know what serialization is? here is a Serialization tutorial.

java.io.Externalizable is an interface unlike java.io.Serializable interface it has two methods called writeExternal() and readExternal(). Externalizable interface is use to serialized an object, but serialization of an object is already achieved by implementing Serializable marker interface then why additional interface called Externalizable?

Well Externalizable interface extends Serializable interface and allows you to customize the default protocol of serialization with the help of writeExternal() and readExternal() methods. The writeExternal() and readExternal() methods gives you the complete control over the format and content of the stream for an object and it's super type.

How to implement Externalizable? Here is a sample program FIFASoccer.java

package com.javamakeuse.poc;

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

public class FIFASoccer implements Externalizable {
 
 private String manufacturer;
 private String model;

 public FIFASoccer() {
  System.out.println("wow constructor called!!");
 }

 public FIFASoccer(String manufacturer, String model) {
  super();
  this.manufacturer = manufacturer;
  this.model = model;
 }

 public String getManufacturer() {
  return manufacturer;
 }

 public void setManufacturer(String manufacturer) {
  this.manufacturer = manufacturer;
 }

 public String getModel() {
  return model;
 }

 public void setModel(String model) {
  this.model = model;
 }

 @Override
 public void writeExternal(ObjectOutput out) throws IOException {
  out.writeObject(manufacturer);
  out.writeObject(model);

 }

 @Override
 public void readExternal(ObjectInput in) throws IOException,
   ClassNotFoundException {
  manufacturer = (String) in.readObject();
  model = (String) in.readObject();

 }
}

FIFASoccer.java class is ready for serialization, Serialization is enabled by implementing Externalizable interface. In FIFASoccer class we overrides the writeExternal() and readExternal() methods and provides the logic of writing object into stream and also restoring objects from the stream. While implementing Externalizable interface you must have to provide public no-arg constructor to getting back (restoring) the object from the stream.
OK now lets serialized the object in FIFASoccerMain.java class

package com.javamakeuse.poc;

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

public class FIFASoccerMain {

 private static String file = "soccer.ser";

 private static void serialized(Object obj) throws IOException {
  FileOutputStream fos = new FileOutputStream(file);
  ObjectOutputStream out = new ObjectOutputStream(fos);
  out.writeObject(obj);
  out.close();

 }

 // Re-store object from the serialized stream
 private static FIFASoccer deSerialized() throws IOException,
   ClassNotFoundException {
  FileInputStream fis = new FileInputStream(file);
  ObjectInputStream in = new ObjectInputStream(fis);
  return (FIFASoccer) in.readObject();
 }

 public static void main(String[] args) {

  try {
   serialized(new FIFASoccer("Adidas", "2014"));
   
   // here default constructor called while restoring object
   FIFASoccer fifaSoccer = deSerialized();
   
   System.out.println("Manufacturer == "+fifaSoccer.getManufacturer());
   System.out.println("Model == "+fifaSoccer.getModel());
   
  } catch (IOException | ClassNotFoundException e) {
   e.printStackTrace();
  }
 }
}

Run the FIFASoccerMain class, it will call the serialized() method to serialized the object and calling deSerialized() method to restore the object from the stream. See the output while de-serialization it'll call the public no-arg constructor of the class.

OUT PUT:
wow constructor called!!
Manufacturer == Adidas
Model == 2014

Although we implement Externalizable interface and overrides the writeExternal() and readExternal() methods, We don't need to explicitly call these method while serializing/deserializing. We just need to call writeObject() and readObject() method and writeExternal() and readExternal() method will call automatically. If the object supports Externalizable interface, then writeExternal() and readExternal() method is called. If the object does not support Externalizable interface and does implement Serializable, the object is saved using ObjectOutputStream.

Secret:

When we call writeObject(obj) method of ObjectOutputStream class to serialized the object, lots of method works around the object to make it serialized, for example it will first check, Is the object is an instance of Serializable interface? using something like below code inside writeObject() method.
if (obj instanceof Serializable) {
writeOrdinaryObject(obj, desc, unshared);
}

The above condition true, Means your class implements Serializable/Externalizable interface now it will proceed for the next label check inside writeOrdinaryObject() method using something like.
if (desc.isExternalizable()) {
writeExternalData((Externalizable) obj);
}

When an Externalizable object is deserialized (reconstructed), an instance is created using the public no-arg constructor,then the readExternal method is called. So If your class implements Externalizable interface then you must have to provide the public no-arg constructor. Otherwise it'll throws java.io.InvalidClassException: no valid constructor.
If your class implements Externalizable interface, means you must have to maintain the logic of serialization yourself unlike Serializable interface, if you add, remove or change a field in your class, you have to change your writeExternal/readExternal methods implementation to reflect the changes.

How to serialized a parent class, If a parent class does not implements Externalizable interface

You can serialized a parent class even if your parent class does not implements Externalizable interface, Only Sub class does implement Externalizable interface below is a sample program to achieve the same.
FIFASoccer.java Parent class.

package com.javamakeuse.poc;

public class FIFASoccer {

 String manufacturer;
 String model;

 public FIFASoccer() {
 }

 public FIFASoccer(String manufacturer, String model) {
  super();
  this.manufacturer = manufacturer;
  this.model = model;
 }

 public String getManufacturer() {
  return manufacturer;
 }

 public void setManufacturer(String manufacturer) {
  this.manufacturer = manufacturer;
 }

 public String getModel() {
  return model;
 }

 public void setModel(String model) {
  this.model = model;
 }

}

FIFA2014.java sub class

package com.javamakeuse.poc;

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

public class FIFA2014 extends FIFASoccer implements Externalizable {

 private String technology;
 private String country;

 public FIFA2014() {
  super();
  // TODO Auto-generated constructor stub
 }

 public FIFA2014(String technology, String country, String model,
   String manufacturer) {
  super();
  this.technology = technology;
  this.country = country;
  super.model = model;
  super.manufacturer = manufacturer;
 }

 public String getTechnology() {
  return technology;
 }

 public void setTechnology(String technology) {
  this.technology = technology;
 }

 public String getCountry() {
  return country;
 }

 public void setCountry(String country) {
  this.country = country;
 }

 @Override
 public void writeExternal(ObjectOutput out) throws IOException {
  // parent class properties
  out.writeObject(manufacturer);
  out.writeObject(model);

  // sub class properties
  out.writeObject(country);
  out.writeObject(technology);
 }

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

  // reading parent class properties
  manufacturer = (String) in.readObject();
  model = (String) in.readObject();

  // reading sub class properties
  country = (String) in.readObject();
  technology = (String) in.readObject();
 }

}

FIFASoccerMain.java to test serialization/deserialization of parent/child class.

package com.javamakeuse.poc;

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

public class FIFASoccerMain {

 private static String file = "fifa2014.ser";

 private static void serialized(Object obj) throws IOException {
  FileOutputStream fos = new FileOutputStream(file);
  ObjectOutputStream out = new ObjectOutputStream(fos);
  out.writeObject(obj);
  out.close();

 }

 // Re-store object from the serialized stream
 private static FIFA2014 deSerialized() throws IOException,
   ClassNotFoundException {
  FileInputStream fis = new FileInputStream(file);
  ObjectInputStream in = new ObjectInputStream(fis);
  return (FIFA2014) in.readObject();
 }

 public static void main(String[] args) {

  try {
   // serializing
   serialized(new FIFA2014("goal line technology", "Brazil", "2014",
     "adidas"));

   // de-serializing
   FIFA2014 fifaSoccer = deSerialized();

   System.out.println("Manufacturer == "
     + fifaSoccer.getManufacturer());
   System.out.println("Host Country== " + fifaSoccer.getCountry());
   System.out.println("Technology == " + fifaSoccer.getTechnology());

  } catch (IOException | ClassNotFoundException e) {
   e.printStackTrace();
  }
 }
}

Run the FIFASoccerMain.java class to serialized/deserialized the parent/child class.

OUT PUT:
Manufacturer == adidas
Host Country== Brazil
Technology == goal line technology

Things to keep in mind while implementing Externalizable

  • Must implements java.io.Externalizable interface.
  • Override the writeExternal and readExternal methods.
  • If you add, remove or change a field in your class, you have to change your writeExternal/readExternal methods.
  • If parent and child both implements Externalizable interface. In writeExternal() method of child class do super.writeExternal(out) and in readExternal() method do super.readExternal(in).


That's it.
Sponsored Links

0 comments:

Post a Comment