Java Externalizable Example – More Efficient Serialization

The default serialization in Java is not efficient. Suppose we serialize a bloated object having lots of attributes that we do not wish to serialize for any reason (e.g., they are always assigned default values). In that case, we get a heavy object to process and send more bytes over the network, which may be costly in some cases.

To solve this issue, we can write custom serialization and deserialization logic by implementing Externalizable interface and overriding its methods writeExternal() and readExternal(). By implementing these methods, we tell the JVM how to encode/decode the object.

public interface Externalizable {

    void readExternal(ObjectInput in)
    void writeExternal(ObjectOutput out)
}

1. Using Externalizable Interface

For example purposes, we have created the UserSettings class which we will serialize and de-serialize using writeExternal() and readExternal() methods.

In the following class, we are not serializing or deserializing the field ‘doNotStoreMe’. Also, consider adding a serialVersionUID field to avoid InvalidClassException when we make incompatible changes to the class structure.

public class UserSettings implements Externalizable {

       private static final long serialVersionUID = 1L;

	public UserSettings(){}

	private String doNotStoreMe;

	private Integer fieldOne;
	private String fieldTwo;
	private boolean fieldThree;

	public String getDoNotStoreMe() {
		return doNotStoreMe;
	}

	public void setDoNotStoreMe(String doNotStoreMe) {
		this.doNotStoreMe = doNotStoreMe;
	}

	public Integer getFieldOne() {
		return fieldOne;
	}

	public void setFieldOne(Integer fieldOne) {
		this.fieldOne = fieldOne;
	}

	public String getFieldTwo() {
		return fieldTwo;
	}

	public void setFieldTwo(String fieldTwo) {
		this.fieldTwo = fieldTwo;
	}

	public boolean isFieldThree() {
		return fieldThree;
	}

	public void setFieldThree(boolean fieldThree) {
		this.fieldThree = fieldThree;
	}

	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
		fieldOne = in.readInt();
		fieldTwo = in.readUTF();
		fieldThree = in.readBoolean();
	}

	public void writeExternal(ObjectOutput out) throws IOException {
		out.writeInt(fieldOne);
		out.writeUTF(fieldTwo);
		out.writeBoolean(fieldThree);
	}

	@Override
	public String toString() {
		return "UserSettings [doNotStoreMe=" + doNotStoreMe + ", fieldOne="
				+ fieldOne + ", fieldTwo=" + fieldTwo + ", fieldThree="
				+ fieldThree + "]";
	}
}

1.1. Externalizable.writeExternal() Example

The writeExternal() method provides the logic for serialization i.e. writing the class fields into bytes. we are free to store only those fields which we want back after reading the serialized object back. Ignore the rest of the fields.

public void writeExternal(ObjectOutput out) throws IOException {

	//We are not storing the field 'doNotStoreMe'

	out.writeInt(fieldOne);
	out.writeUTF(fieldTwo);
	out.writeBoolean(fieldThree);
}

1.2. Externalizable.readExternal() Example

The only thing we need to remember is that the readExternal() method must deserialize the values in the same sequence and with the same types as were written by writeExternal().

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

	fieldOne = in.readInt();
	fieldTwo = in.readUTF();
	fieldThree = in.readBoolean();
}

2. Complete Example

Now let’s write the code to serialize and read back the bytes to verify if JVM honors the contract.

public class ExternalizableExample {
	public static void main(String[] args) {

		UserSettings settings = new UserSettings();
		settings.setDoNotStoreMe("Sensitive info");
		settings.setFieldOne(10000);
		settings.setFieldTwo("HowToDoInJava.com");
		settings.setFieldThree(false);

		//Before
		System.out.println(settings);

                //After
		storeUserSettings(settings);
		UserSettings loadedSettings = loadSettings();
		System.out.println(loadedSettings);
	}

	private static UserSettings loadSettings() {
        try {
            FileInputStream fis = new FileInputStream("object.ser");
            ObjectInputStream ois = new ObjectInputStream(fis);
            UserSettings settings =  (UserSettings) ois.readObject();
            ois.close();
            return settings;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

	private static void storeUserSettings(UserSettings settings)
	{
		try {
            FileOutputStream fos = new FileOutputStream("object.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(settings);
            oos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
	}
}

The program output:

UserSettings [doNotStoreMe=Sensitive info, fieldOne=10000, fieldTwo=HowToDoInJava.com, fieldThree=false]
UserSettings [doNotStoreMe=null, fieldOne=10000, fieldTwo=HowToDoInJava.com, fieldThree=false]

Clearly, we are able to fetch back desired fields while ignoring the unwanted fields and that’s the whole purpose of Externalizable interface.

3. Difference between Externalizable and Serializable

The following tables summarise the main differences between the Serializable and Externalizable interfaces:

FeatureSerializableExternalizable
(De)serialization done by?JVM bears full responsibility for performing serialization and deserialization.The programmer must write the custom logic for serialization and deserialization.
When to use?Need to serialize the whole object.For partial serialization.
PerformanceRelatively slow due to reflection in runtime.Fast due to complete control over the process.
Read/Write OrderNo ordering is needed. Must be read in the same order, fields were written.

Happy Learning !!

Comments

Subscribe
Notify of
guest
2 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode