In Java development, object serialization is the process of converting an object's state into a byte stream, allowing it to be persisted to a file, database, or transmitted over a network. Because Java is an object-oriented language, the capabilities and traits of classes propagate down the inheritance hierarchy. A fundamental rule of this system is that if a superclass implements the java.io.Serializable interface, all of its subclasses automatically inherit serializability. The subclass does not need to declare implements Serializable in its header class definition. The JVM automatically recognizes the child class as serializable through its inheritance lineage. In this guide, we will analyze how serialization propagates down the class hierarchy and examine what happens when the parent class is not serializable.
To visualize this inheritance, imagine a nation's citizenship and travel laws:
- The Parent (Superclass): A parent gains citizenship in a country and successfully applies for a passport (representing the
Serializablemarker interface). - The Child (Subclass): Because of their direct lineage, the child naturally inherits citizenship and the right to obtain a passport. The child does not need to go through the naturalization process from scratch or submit independent applications. The citizenship status is automatically part of their identity because of their parent's status.
Deserialization & The Non-Serializable Parent Scenario
While subclass serialization is automatic, there is a critical rule regarding classes that do not implement Serializable:
- Serializable Parent: If the parent class is serializable, Java serializes both the parent and child field states. During deserialization, Java restores the entire object hierarchy using the serialized byte data.
- Non-Serializable Parent: If a child class wants to be serializable but its parent class is not serializable, serialization is still possible. To do this, the parent class must declare an accessible no-argument constructor (either public or protected). During deserialization, Java skips the constructor of the serializable child class and reconstructs its fields from the serialized byte stream. However, for the non-serializable parent, Java invokes the no-argument constructor to initialize the parent's portion of the object state. If the non-serializable parent does not have a no-argument constructor, a runtime
InvalidClassExceptionwill be thrown instantly during the deserialization phase.
Java Implementation Code
Below is the complete Java implementation showcasing a parent class implementing Serializable and a subclass inheriting it, writing the object state to a binary file:
package io.practise;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
// If a class implements Serializable, all its subclasses are also serializable
class SuperclassPerson implements Serializable {
int id;
String name;
SuperclassPerson(int id, String name) {
this.id = id;
this.name = name;
}
}
class SubclassStudent extends SuperclassPerson {
String course;
int fee;
public SubclassStudent(int id, String name, String course, int fee) {
super(id, name);
this.course = course;
this.fee = fee;
}
}
public class Serialiseisa {
public static void main(String args[]) throws Exception {
SubclassStudent s1 = new SubclassStudent(211, "ravi", "Java Concurrency", 300);
// Write subclass student object to file
FileOutputStream fout = new FileOutputStream("serialise.ser");
ObjectOutputStream out = new ObjectOutputStream(fout);
out.writeObject(s1);
out.flush();
out.close();
System.out.println("Serialization success");
}
}
Conclusion & Best Practices
Inheriting serializability simplifies domain model design, as you only need to declare the interface at the root level of your entity models. However, you must be careful: if you inherit serializability, all subclass fields must also be serializable or marked as transient. Additionally, always declare a unique serialVersionUID in your classes to ensure versions remain compatible across JVM executions, even when class properties undergo minor refactoring.