父类未实现serializable接口不会抛notserializableexception,但其字段不参与序列化,反序列化时通过调用父类无参构造器初始化为默认值;若父类无可用无参构造器则抛invalidclassexception或instantiationexception。

Java 反序列化时,父类未实现 Serializable 接口不会直接抛出 NotSerializableException,但会引发隐性状态丢失或运行时异常——关键在于反序列化重建对象的过程依赖父类构造器,且父类字段完全不参与序列化流程。
父类字段不序列化是默认行为,不是异常
只要父类没声明 implements Serializable,它定义的所有实例字段(无论 public/protected/private)都不会写入字节流,也不会在反序列化时恢复。反序列化时 JVM 仅用子类的 serialVersionUID 和可序列化字段重建子类部分,父类部分靠调用其无参构造器“重置”:
- 字段值全部变为默认值(
null、0、false) - 这不是数据“丢失”,而是压根没被写进去
- 不会报
NotSerializableException,因为序列化器只检查当前类是否可序列化,不校验父类
真正会报异常的情况:父类无可用无参构造器
反序列化必须调用父类的无参构造器来初始化父类部分。若该构造器不存在或不可访问,就会抛出:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
java.io.InvalidClassException: no valid constructorjava.lang.InstantiationException
常见触发场景:
- 父类只定义了带参构造器,且没显式声明无参构造器
- 父类无参构造器是
private或protected且子类不在同一包内 - 父类是 JDK 或第三方库类(如
ArrayList的某些定制子类),无法修改源码
安全反序列化的两种可行路径
当无法让父类实现 Serializable 时,需确保父类具备可访问的无参构造器,并配合子类手动接管字段逻辑:
-
轻量解法(推荐优先尝试):给父类加一个
protected Parent() {}构造器。不需要改接口,只要构造器存在且子类能访问即可 -
定制读取法(父类不可改时):在子类中定义
private void readObject(ObjectInputStream in)方法:
– 先调用in.defaultReadObject()恢复子类字段
– 再通过反射或已知逻辑,把父类字段值从流中读出并赋值(如in.readInt()对应父类int id)
– 前提是父类字段类型可序列化,且你清楚字段顺序和类型
serialVersionUID 必须显式声明
父类未实现 Serializable 会导致子类默认计算的 serialVersionUID 不稳定(受父类结构影响)。一旦父类后续修改,子类反序列化可能失败:
- 务必在子类中显式声明:
private static final long serialVersionUID = 1L; - 不要依赖 IDE 自动生成值,否则不同编译环境结果可能不一致
- 若父类字段逻辑被手动恢复,
serialVersionUID应与历史序列化版本保持一致
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










