Superclass Is Not Serializable
However, the result of deserialization is not the same when the superclass Person is not serializable, but the subclass Student is. We get the following output from the program in Example 20.9 when it is run with (1b) and (3b) in the Person class and the Student class, respectively—that is, when only the subclass is serializable, but not the superclass. The output shows that the object state prior to serialization is not identical to the object state after deserialization.
Before writing: Student state(Pendu, 1007)
No-argument constructor executed.
After reading: Student state(null, 1007)
During deserialization, the zero-argument constructor of the Person superclass at (2) is run. As we can see from the declaration of the Person class in Example 20.9, this zero-argument constructor does not initialize the name field, which remains initialized with the default value for reference types (null).
If the superclass Person does not provide the no-argument constructor or the default constructor, as in the declaration below, the call to the readObject() method to perform deserialization throws an InvalidClassException.
public class Person { // (1b)
private String name;
public Person(String name) { this.name = name; }
public String getName() { return name; }
}
Output from the program (edited to fit on the page):
Before writing: Student state(Pendu, 1007)
Exception in thread “main” java.io.InvalidClassException:
Student; no valid constructor
…
at SerialInheritance.main(SerialInheritance.java:28)
The upshot of serializing objects of subclasses is that the superclass should be serializable, unless there are compelling reasons for why it is not. And if the superclass is not serializable, it should at least provide either the default constructor or the no-argument constructor to avoid an exception during deserialization.
Although a superclass might be serializable, its subclasses can prevent their objects from being serialized by implementing the private method writeObject (ObjectOutputStream) that throws a java.io.NotSerializableException.
Example 20.9 Serialization and Inheritance
import java.io.Serializable;
// A superclass
public class Person implements Serializable { // (1a)
//public class Person { // (1b)
private String name;
public Person() { // (2)
System.out.println(“No-argument constructor executed.”);
}
public Person(String name) { this.name = name; }
public String getName() { return name; }
}
import java.io.Serializable;
public class Student extends Person { // (3a)
//public class Student extends Person implements Serializable { // (3b)
private long studNum;
public Student(String name, long studNum) {
super(name);
this.studNum = studNum;
}
@Override
public String toString() {
return “Student state(” + getName() + “, ” + studNum + “)”;
}
}
import java.io.*;
public class SerialInheritance {
public static void main(String[] args)
throws IOException, ClassNotFoundException {
// Serialization:
try (// Set up the output stream: (4)
FileOutputStream outputFile = new FileOutputStream(“storage.dat”);
ObjectOutputStream outputStream = new ObjectOutputStream(outputFile)) {
// Write data:
Student student = new Student(“Pendu”, 1007);
System.out.println(“Before writing: ” + student);
outputStream.writeObject(student);
}
// Deserialization:
try (// Set up the input stream: (5)
FileInputStream inputFile = new FileInputStream(“storage.dat”);
ObjectInputStream inputStream = new ObjectInputStream(inputFile)) {
// Read data.
Student student = (Student) inputStream.readObject();
// Write data on standard output stream.
System.out.println(“After reading: ” + student);
}
}
}