java 对象序列化中,父类字段能否被序列化取决于父类是否实现了 serializable 接口。如果父类实现了该接口,其非静态、非瞬态字段会自动参与序列化;如果父类未实现该接口,则必须提供无参构造函数,并在子类的 writeobject() 和 readobject() 方法中手动调用 super.writeobject() 和 super.readobject() 来确保父类状态被正确保存和恢复。

父类实现 Serializable 时的自动序列化机制
当父类直接实现 Serializable 接口时,子类无需任何特殊处理即可序列化父类字段。JVM 的默认序列化机制会递归地遍历对象图,将父类和子类的所有可序列化字段写入流中。这种场景下,只需确保所有字段类型本身也是可序列化的即可。

import java.io.*;
// 父类实现 Serializable
public class Parent implements Serializable {
private String parentField = "parentValue";
}
// 子类继承父类
public class Child extends Parent implements Serializable {
private String childField = "childValue";
public static void main(String[] args) throws Exception {
// 序列化
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(new Child());
}
// 反序列化
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
try (ObjectInputStream ois = new ObjectInputStream(bais)) {
Child obj = (Child) ois.readObject();
System.out.println("Parent Field: " + obj.parentField);
System.out.println("Child Field: " + obj.childField);
}
}
}
运行上述代码,控制台输出显示父类字段 parentField 和子类字段 childField 均被成功保留。这是因为 Parent 类实现了 Serializable,JVM 在序列化 Child 实例时,会自动包含其父类的状态。
父类未实现 Serializable 时的手动处理
若父类未实现 Serializable,但子类实现了,则父类字段不会被自动序列化。此时,父类必须提供一个公共的无参构造函数,否则在反序列化时会抛出 InvalidClassException。子类需要重写 writeObject() 和 readObject() 方法,显式调用 super.writeObject() 和 super.readObject() 来处理父类部分。

import java.io.*;
// 父类未实现 Serializable
public class NonSerializableParent {
private String parentField = "parentValue";
// 必须有无参构造函数
public NonSerializableParent() {}
}
// 子类实现 Serializable
public class SerializableChild extends NonSerializableParent implements Serializable {
private String childField = "childValue";
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(parentField); // 手动序列化父类字段
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
parentField = (String) in.readObject(); // 手动反序列化父类字段
}
public static void main(String[] args) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(new SerializableChild());
}
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
try (ObjectInputStream ois = new ObjectInputStream(bais)) {
SerializableChild obj = (SerializableChild) ois.readObject();
System.out.println("Parent Field: " + obj.parentField);
System.out.println("Child Field: " + obj.childField);
}
}
}
在此示例中,由于 NonSerializableParent 未实现 Serializable,我们必须在 SerializableChild 中手动处理父类字段的序列化。通过 out.writeObject(parentField) 和 in.readObject(),我们确保了父类状态的正确传递。注意,父类必须有无参构造函数,否则反序列化时会失败。
父类字段为 transient 时的处理策略
即使父类实现了 Serializable,如果其字段被声明为 transient,这些字段也不会被自动序列化。对于 transient 字段,开发者需要在 writeObject() 和 readObject() 中手动处理其状态,或者在反序列化后通过其他方式(如重新计算或从数据库加载)恢复其值。这适用于那些不需要持久化或可以从其他来源派生的字段。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











