In this article, we will discuss externalizable interface with an example to save and 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
1. 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 it 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 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 of all member variables of an Object, even if programmer requires only couple of variables to be saved/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
1.1 Advantage of Externalizable over Serializable :
- Allows saving/restoring partial object i.e.; 2 or 3 member variables of an object out of total object
- As programmer has to code/write custom logic for serialization and de-serialization process, so write/code 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 control over saving/restoring object and can easily ignore those variables whose value is secure or need to kept very secret
- By saving/restoring partial object instead of total object, time consumption decreases i.e.; time is saved in externalizable interface
2. 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
Q) Write complete method signature of 2 methods ?
- Method signature :
// writeExternal method
public void writeExternal(ObjectOutput out) throws IOException {
}
// readExternal method
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
}
3. Example on Externalizable interface:
- Customer class implementing Externalizable interface
- Serialization and De-serialization using Externalizable interface
- Exception scenario
3.1 Customer class implementing Externalizable interface :
- 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/restoring object
- For partial serialization, we have to override 2 methods namely,
writeExternal(); –> for saving/writing in serialization process
readExternal(); –> for restoring during de-serialization process
3.1.1 Custom Serialization:
- During serialization inside writeExternal(); method, programmer has to code/write custom logic to save/persist 2 member variables
3.1.2 Custom 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
+ "]";
}
}
3.2 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
3.3 Exception scenario :
- Let us tweak above example by removing public no-arg constructor
- 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
Related Articles:
- Java – Serialization and De-Serialization Tutorial Index
- Java – Introduction to Serialization and De-Serialization
- Java – Serializable interface
- Java – Transient keyword with Serialization
- Java – Transient keyword with static variable in Serialization
- Java – Transient keyword with final variable in Serialization
- Java – Serializing a variable with transient modifier or keyword
- Java – Order of Serialization and De-Serialization
- Java – Serialization with Aggregation
- Java – Serialization with Inheritance
- Java – Externalization in detail
- Java – Serializable v/s Externalizable
- Java – Importance of SerialVersionUID in Serialization
- Java – Singleton Design pattern with Serialization
- Java – How to construct a singleton class in a multi-threaded environment ?
- Java – Singleton design pattern, restricting Object creation by overriding readResolve() method
- Java – How to stop Serialization ?
- Java – How to serialize and de-serialize ArrayList ?
- Java – Interview question & answers on Serialization and Externalization
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
Happy Coding !!
Happy Learning !!