Externalizable Interface in Java
The Externalizable interface in Java, in java.io, extends Serializable and gives a class complete control over how it is serialized. Instead of Java saving fields automatically, the class implements two methods: writeExternal, which writes exactly the data you choose, and readExternal, which reads it back in the same order. An Externalizable class must also have a public no-argument constructor, because Java calls it to create the object before readExternal runs. In this lesson, you will learn how to implement it and how it compares with Serializable.
Declaration
public interface Externalizable extends Serializable {
void writeExternal(ObjectOutput out) throws IOException;
void readExternal(ObjectInput in)
throws IOException, ClassNotFoundException;
}Example: A Compact Student
Let's see an example that saves only a name and marks, in a compact form.
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
public class ExternalDemo {
public static class Student implements Externalizable {
private String name;
private int marks;
private String grade;
public Student() {
System.out.println("No-arg constructor called");
}
Student(String name, int marks) {
this.name = name;
this.marks = marks;
this.grade = marks >= 90 ? "A" : "B";
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(name);
out.writeInt(marks);
}
@Override
public void readExternal(ObjectInput in) throws IOException {
name = in.readUTF();
marks = in.readInt();
grade = marks >= 90 ? "A" : "B";
}
@Override
public String toString() {
return name + " " + marks + " " + grade;
}
}
public static void main(String[] args)
throws IOException, ClassNotFoundException {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
try (ObjectOutputStream out = new ObjectOutputStream(bytes)) {
out.writeObject(new Student("Navika", 91));
}
try (ObjectInputStream in = new ObjectInputStream(
new ByteArrayInputStream(bytes.toByteArray()))) {
System.out.println("Read back: " + in.readObject());
}
}
}No-arg constructor called
Read back: Navika 91 AExplanation: writeExternal writes only name and marks; grade is never saved. When reading, Java first calls the public no-argument constructor, then readExternal reads the two values in the same order and recalculates grade. The class decides everything about its stored form.
Serializable vs Externalizable
Serializable | Externalizable | |
|---|---|---|
| Methods to implement | None | writeExternal, readExternal |
| What is saved | All non-transient fields, automatically | Only what you write |
| Superclass fields | Handled automatically | You must write them yourself |
| Constructor on reading | Not called (except non-serializable parents) | Public no-arg constructor is called |
transient | Respected | Irrelevant; you choose |
| Effort | Low | Higher, but full control |
| Typical use | Most cases | Compact formats, performance, versioning control |
Common Mistakes
Forgetting the public no-argument constructor. Reading fails with InvalidClassException: no valid constructor.
Reading in a different order than writing. Values end up in the wrong fields.
Forgetting superclass state. Externalizable saves nothing automatically.
Interview Corner
What is the difference between Serializable and Externalizable?
Serializable is a marker interface: the JVM automatically saves all non-static, non-transient fields, including those of serializable superclasses, and doesn't call the class's constructor when reading. Externalizable extends it and requires writeExternal and readExternal, where the class writes and reads its own data; nothing is saved automatically, and a public no-argument constructor is called before readExternal. Externalizable gives full control and can be more compact, at the cost of more code.
Practice
- Easy: Make a
Pointclass withxandyimplementExternalizableand round-trip it. - Harder: Add a version number as the first value written by
writeExternal, and makereadExternalhandle both version 1 (name only) and version 2 (name and marks).
Key Takeaways
Was this tutorial helpful?