Java Externalizable Example – More Efficient Serialization

The default java serialization is not efficient. It you serialize a bloated objected having lots of attributes and properties, you do not wish to serialize for any reason (e.g. they always been assigned default values), you get heavy object to process and send more bytes over network which may be costly on some cases.

To solve this issue, you can write your own serialization logic by implementing Externalizable interface and overriding it’s methods writeExternal() and readExternal(). By implementing these methods, you are telling the JVM how to encode/decode your object.

For example purpose, I have created this simple class which we will serialize and de-serialize using writeExternal() and readExternal() methods.

class UserSettings implements Externalizable {
	
	//This is required
	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 + "]";
	}
}

Externalizable writeExternal() Example

writeExternal() method is used to provide the logic for serialization i.e. writing the fields of class into bytes. You are free to store only those fields which you want back after reading the serialized object back. Ignore rest of the field.

public void writeExternal(ObjectOutput out) throws IOException {

	//We are not storing the field 'doNotStoreMe'

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

Externalizable readExternal() Example

Only thing you need to remember is – The readExternal() method must read 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();
}

Complete Example

Now let’s write the code to serialize and read back the bytes to verify if JVM honor 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);
		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();
        }
	}
}
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 whole purpose of Externalizable interface.

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

2 thoughts on “Java Externalizable Example – More Efficient Serialization”

  1. Hi lokesh, we can also use the transient keyword before the attributes to avoid from the serialization. M I right ? Then in which case/scenario we should use externalize ??

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.