java序列化中父类未实现serializable时,其字段完全不参与序列化,反序列化时通过调用父类无参构造器初始化为默认值;成功与否取决于该构造器是否可访问。

Java 序列化机制对父类未实现 Serializable 接口的情况有明确且严格的处理规则:父类字段**完全不参与序列化过程**,反序列化时通过调用父类无参构造器重建,并将所有字段初始化为默认值(null、0、false),而不是“丢失”或“报错”。是否能成功反序列化,关键取决于父类是否有可访问的无参构造器。
父类字段根本不会被写入字节流
序列化不是继承行为,而是逐类检查 Serializable 契约的过程。只要某一级父类没有实现该接口,它声明的所有非 static、非 transient 实例字段(包括泛型字段如 ID id)都会被跳过:
- 不会出现在输出字节流中
- 反序列化时不会尝试恢复这些字段的原始值
- 子类自身字段照常序列化,不受影响
反序列化依赖父类无参构造器
JVM 在反序列化子类对象时,会沿着继承链向上,为每一级未实现 Serializable 的父类调用其无参构造器来初始化该部分对象。这一步失败,整个反序列化就中断:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 父类有
public Base() {}→ 可成功重建,字段全为默认值 - 父类只有带参构造器(如
Base(String id))→ 抛InvalidClassException: no valid constructor - 父类无参构造器是
private或protected(且子类不在同一包)→ 同样失败
两种可行的补救方式
当父类字段状态必须保留时,不能依赖默认行为,需主动干预:
-
推荐方案:让父类实现
Serializable(若代码可控)
只需添加implements Serializable和显式private static final long serialVersionUID,无需改动子类逻辑,安全简洁 -
兜底方案:子类重写
writeObject/readObject(适用于第三方父类)
在writeObject中先调用defaultWriteObject(),再用out.writeXXX()显式写出父类字段;
在readObject中先调用defaultReadObject(),再用in.readXXX()读回并赋值(需字段可访问,或通过 public/protected setter)
继承链中断会影响整条路径
序列化能力不跨级传递。例如:
- A → B → C,仅 C 实现
Serializable:只有 C 的字段被保存,A 和 B 的字段全部清零 - A → B → C,A 和 C 实现,B 未实现:A 的字段能保留(因 A 自身可序列化),B 的字段丢失,C 的字段保留
- 只要中间某级不可改,就必须由最近的可修改子类承担字段接管责任
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










