java序列化在继承链中不自动穿透,父类字段是否保留取决于每级父类是否实现serializable接口;未实现的父类字段不会被序列化,反序列化时通过其无参构造器初始化为默认值。

Java 序列化在继承体系中不是自动“穿透”的,是否保留父类字段,取决于每一级父类是否显式实现 Serializable 接口。关键不在子类有没有实现,而在于整个继承链上每层是否“签了契约”。
父类未实现 Serializable:字段直接丢失,反序列化时重置为默认值
只要某一级父类(哪怕只是祖父类)没实现 Serializable,它声明的所有实例字段都不会进入字节流。子类即使实现了接口,也只能序列化自己定义的字段。
- 反序列化时,JVM 会调用该父类的无参构造器(必须存在且可访问)来重建父类部分
- 此时所有未序列化的字段按 Java 默认规则初始化:
null(引用)、0(数值)、false(布尔) - 原始值完全不可恢复——不是“没读到”,而是根本没写进去
能改父类时:最稳妥的做法是让它也实现 Serializable
如果父类是你自己维护的代码,直接让它实现接口,并添加 serialVersionUID:
- 避免手动序列化带来的逻辑错漏和后续维护负担
- 泛型不影响——如
Entity<id></id>只要声明了Serializable,其字段就能正常参与序列化 - 子类仍建议显式声明自己的
serialVersionUID,防止因父类版本变更引发兼容性问题
父类不可改(如第三方类):子类需手动接管字段序列化
当父类来自 SDK 或框架、无法修改时,最近的可修改子类必须通过自定义 writeObject 和 readObject 补救:
-
writeObject中先调用defaultWriteObject()序列化子类字段,再用out.writeInt()等显式写出父类字段值 -
readObject中先调用defaultReadObject()恢复子类字段,再用in.readInt()等逐个读回并赋给父类字段(需父类提供相应 setter 或字段为protected) - 前提是父类必须有可访问的无参构造器,否则反序列化会抛
InvalidClassException
继承链中任意一级中断,都会截断字段传递
序列化不看“继承关系”,只逐类检查 Serializable 声明。例如:
- A → B → C,仅 C 实现:只有 C 的字段被保存,A 和 B 的字段全部丢失
- A → B → C,A 和 C 实现、B 未实现:A 的字段能保留(A 自身可序列化),B 的字段丢失,C 的字段保留
- 只要中间某级缺失接口且不可改,就必须在它之下第一个可改的子类中兜底处理
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











