Externalizable interface and its implementation in Java with Example
|Welcome geeks, in this java tutorial we will discuss about the Object serialization and deserialization but this time it is going to be in a much controlled way i.e. in a custom manner with full control and all this could be achieved by using the Externalizable interface which is also a sub-interface of Serializable interface. So before you go further have a look at how to use Serializable interface and what are the differences between Serializable and Externalizable Interface.
Main Methods used –
Externalization is nothing but Serialization by using Externalizable interface and implementing its two main methods
- void readExternal(ObjectInput in) – This method uses methods of DataInput for storing primitive data types and for complex objects like Strings, Arrays etc it uses readObject method.
- void writeExternal(ObjectOutput out) – This method uses methods of DataOutput for restoring primitive data types and for complex objects like Strings, Arrays etc it uses writeObject method of ObjectOutput.
So the main question is –
How this process of serialization and deserialization is performed using Externalizable interface?
Whenever there is a call for Serialization process JVM first checks whether the class implements Externalizable interface and if the objects supports this interface then the object is serialized using the writeExternal() method but if the object does not supports Externalizable but implements Serializable then the object is serialized using the ObjectOutputStream.
Similarly during the deserialization process readExternal() method of Externalizable interface is used to reconstruct the object but if no support for Externalizable interface is there but Serializable interface is implemented then it uses ObjectInputStream for the object reconstruction process.
Note :– There should be a public no-arg constructor available in the class to be serialized, this is a must condition because in this case since no reflection API is used and only the identity of the class is written to the stream hence rest of the implementation is left for the class and due to this first an object is created using a public no-arg constructor and this is why it ensures the full control over the serialization and deserialization process.
Externalizable Interface example with no Inheritance
Note :– Kindly Read the comments carefully. They might contain some small and important points.
1.) Car.Java
package com.codingeek.externalizable; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; public class Car implements Externalizable { private Integer ccOfEngine; private String licenseNumber; private Integer numberOfDoors; public Integer getCcOfEngine() { return ccOfEngine; } public void setCcOfEngine(Integer ccOfEngine) { this.ccOfEngine = ccOfEngine; } public String getLicenseNumber() { return licenseNumber; } public void setLicenseNumber(String licenseNumber) { this.licenseNumber = licenseNumber; } public Integer getNumberOfDoors() { return numberOfDoors; } public void setNumberOfDoors(Integer numberOfDoors) { this.numberOfDoors = numberOfDoors; } @Override public String toString() { return "Car [ccOfEngine=" + ccOfEngine + ", licenseNumber=" + licenseNumber + ", numberOfDoors=" + numberOfDoors + "]"; } @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeInt(ccOfEngine); out.writeObject(licenseNumber); // out.writeInt(numberOfDoors); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { ccOfEngine = in.readInt(); licenseNumber = String.valueOf(in.readObject()); // numberOfDoors = in.readInt(); } }
2.) SerializationUtil.Java
package com.codingeek.externalizable; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** * This class is a utility class for performing the serialization and * deserialization operations provided the required information. */ public class SerializationUtil { /** * deserialize to Object from given file. We use the general Object so as * that it can work for any Java Class. */ public static Object deserialize(String fileName) throws IOException, ClassNotFoundException { FileInputStream fis = new FileInputStream(fileName); BufferedInputStream bis = new BufferedInputStream(fis); ObjectInputStream ois = new ObjectInputStream(bis); Object obj = ois.readObject(); ois.close(); return obj; } /** * serialize the given object and save it to given file */ public static void serialize(Object obj, String fileName) throws IOException { FileOutputStream fos = new FileOutputStream(fileName); BufferedOutputStream bos = new BufferedOutputStream(fos); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(obj); oos.close(); } }
3.) SerializationTest.Java
package com.codingeek.externalizable; import java.io.IOException; public class SerializationTest { public static void main(String[] args) { Car car = new Car(); car.setCcOfEngine(1000); car.setLicenseNumber("AW-23-6528"); car.setNumberOfDoors(4); try { /** * Serializing the object */ SerializationUtil.serialize(car, "serialization.txt"); /** * Deserializing the object */ Car carOutput = (Car) SerializationUtil .deserialize("serialization.txt"); System.out.println(carOutput.toString()); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } }
Output:-
Car [ccOfEngine=1000, licenseNumber=AW-23-6528, numberOfDoors=null]
** Suprisingly the output does not contain the value of numberOfDoors and this is because we have commented the lines to save and read the value of this variable in class Car.java.
If you remove the comments from both the places i.e. line no 47 and 55 of class Car.java you can see the difference in the output as below. This time we value of numberOfDoors will also display.
Output:- Car [ccOfEngine=1000, licenseNumber=AW-23-6528, numberOfDoors=4]
Most Important:- One of the most important thing to remember is that the order of storing the variables in method writeExternal should be same as of the variables to be read in method readExternal in the class implementing Externalizable interface.
Share the wisdom with your loved ones.
Using a decent serialization implementation (e.g. fst serialization) implementing externalizable manually almost never pays off. Don’t do it if not proven useful. (see http://java-is-the-new-c.blogspot.de/2013/10/still-using-externalizable-to-get.html )