父类构造器是否被调用取决于其是否实现Serializable:若实现,则反序列化不调用任何构造器;若未实现,则必须提供可访问的无参构造器,否则抛出异常。
java序列化过程中,父类构造器是否被调用、何时被调用、为何有时必须存在,取决于父类是否实现serializable接口——这是理解整个机制的核心分水岭。
父类实现Serializable:反序列化不触发任何构造器
当父类(包括Object)实现了Serializable,整个继承链上的字段都会被序列化保存。反序列化时,JVM直接从字节流中恢复对象状态,跳过所有构造器执行过程。
这意味着:
- 父类和子类的构造器在反序列化时完全不运行
- 即使父类构造器里有打印语句或资源初始化逻辑,也不会执行
- 对象字段值来自序列化数据,而非构造器赋值
父类未实现Serializable:反序列化强制调用其无参构造器
若父类没有实现Serializable,它不会被序列化,其字段也不会写入字节流。反序列化时,JVM需重建该父类部分——只能通过调用其**无参构造器**来完成。
关键限制就在这里:
- 父类必须提供可访问的无参构造器(public / protected / default)
- 如果父类只定义了带参构造器,且未显式声明无参构造器,反序列化会抛出
InvalidClassException或NoSuchMethodException - 子类构造器本身在反序列化中也不会执行(除非父类可序列化)
构造器调用链仅发生在“非序列化创建对象”场景
日常用new Child()创建对象时,构造器按继承链自上而下执行:Object → 父类 → 子类。但这个顺序与序列化无关。
容易混淆的点是:有人看到序列化前new对象时打印了父类构造日志,就误以为反序列化也会如此。其实那是普通对象创建行为,不是序列化机制本身的要求。
绕过父类无参构造限制的实用方案
当无法修改父类(如第三方库类),又必须让子类支持序列化时,可用以下方式规避:
- 在父类中添加一个
protected或包级可见的无参构造器(如有修改权限) - 使用
serialPersistentFields配合writeObject/readObject自定义序列化逻辑,手动控制父类字段读写 - 将父类字段声明为
transient并自行在readObject中恢复(适用于可重建的简单状态)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











