子类字段能正常序列化和反序列化,父类字段因未实现serializable被跳过并重置为默认值;父类必须有可访问的无参构造器,否则反序列化失败;可通过重写writeobject/readobject手动处理父类字段。

Java 序列化时,如果父类没实现 Serializable,子类的实例化属性(即子类自己声明的字段)能正常序列化和反序列化,但父类字段会被跳过——不影响子类字段的保存与恢复。
子类字段不受影响,照常序列化
只要子类显式实现了 Serializable,它自己定义的所有非 transient、非 static 字段都会被写入字节流,反序列化后值保持不变。
- 例如:
User extends Entity<long></long>,User自己的name、email等字段会被完整保留 - 父类
Entity的id字段不会写入,但子类字段完全不受干扰 - 即使父类构造器里给字段赋了初值,反序列化时这些初值也不会“带回来”
父类字段在反序列化时重置为默认值
反序列化过程中,JVM 会调用父类的无参构造器来初始化父类部分。此时所有未被序列化的父类字段按 Java 规则设为默认值:
- 引用类型(如
ID id)→null - 数值类型(如
int age)→0 - 布尔类型(如
boolean active)→false
注意:这个过程不依赖父类是否实现了 Serializable,只依赖它是否有可访问的无参构造器。
必须确保父类有可访问的无参构造器
否则反序列化直接失败,抛出 InvalidClassException: no valid constructor。
- 父类有
public Entity() { }→ 可以成功反序列化(父类字段为默认值) - 父类只有
Entity(Long id)构造器 → 反序列化报错 - 父类无参构造器是
private或protected→ 若子类无法访问,同样失败
想保留父类字段?得手动处理
当无法修改父类源码(比如它是第三方库中的类),可在子类中自定义序列化逻辑:
- 重写
private void writeObject(ObjectOutputStream out) - 先调用
out.defaultWriteObject()序列化子类字段 - 再用
out.writeLong(getId())等方式显式写出父类字段值 - 对应地,重写
private void readObject(ObjectInputStream in) - 先调用
in.defaultReadObject()恢复子类字段 - 再用
setId(in.readLong())等方式把值设回父类字段
前提是父类提供可读写的 getter/setter,且字段状态能通过这些方法完整重建。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











