You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java序列化与继承:反序列化时无参构造方法的调用主体疑问

解答:反序列化时父类无参构造的调用主体

这个问题问到了Java序列化继承场景里的核心细节,我来给你拆解清楚:

当子类实现Serializable但父类未实现时,Java的反序列化机制(具体由ObjectInputStream类的底层逻辑触发)会调用父类的无参构造方法。

背后的核心逻辑

Java序列化的规则很明确:只有实现Serializable接口的类,其字段才会被写入序列化流;未实现该接口的父类,它的字段不会被序列化保存。当反序列化子类对象时:

  1. JVM会先从序列化流中恢复子类的状态(比如你的子类B的j字段);
  2. 对于未被序列化的父类A,JVM无法从流中获取它的状态,所以会通过调用父类的无参构造方法来初始化父类实例——这是JVM确保父类部分能正确初始化的唯一方式。

结合你的代码验证

看你的代码,父类A的无参构造里有打印日志。当你反序列化B的对象时,控制台会输出A's class constructor called,这就是反序列化机制主动触发的。如果A没有定义无参构造,反序列化时会直接抛出InvalidClassException,因为JVM找不到合适的构造方法来初始化父类。

你可以跑下面这段测试代码来直观验证:

import java.io.*;

public class TestDeserialization {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 先序列化一个B对象
        B b = new B();
        b.j = 100;
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("b.ser"));
        oos.writeObject(b);
        oos.close();

        // 执行反序列化
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("b.ser"));
        B deserializedB = (B) ois.readObject();
        ois.close();
        // 此时会看到A的无参构造日志,且deserializedB的i值为50(来自A的无参构造),j值为100(来自序列化流)
    }
}

总结一下:既不是子类主动调用,也不是你写的业务代码触发,而是Java反序列化的底层机制(ObjectInputStream的处理流程中)自动调用了父类的无参构造,用来初始化未被序列化的父类部分。

内容的提问来源于stack exchange,提问作者elvis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:56:42