父类静态变量在子类首次主动使用时,由JVM沿继承链自顶向下初始化且仅一次;触发条件包括new子类、访问子类非编译期常量静态成员、反射加载子类;初始化严格按源码顺序执行静态变量赋值和static块。

父类静态变量在子类首次主动使用时,由 JVM 沿继承链自顶向下触发初始化,且仅执行一次。
父类静态变量初始化的触发时机
不是创建子类对象才开始,而是第一次主动使用子类(或其父类)时,JVM 就会检查并加载整个继承链上的类。只要涉及以下任一操作,就会触发父类静态初始化:
- new 子类实例(如
new Child()) - 访问子类的静态字段(非编译期常量)或调用子类静态方法
- 反射获取子类 Class 对象(
Class.forName("Child"))
此时 JVM 先加载并初始化 Grandparent → Parent → Child 的静态部分,顺序不可跳过、不可倒置。
初始化过程严格按源码顺序执行
对父类而言,静态变量和静态代码块的执行顺序就是它们在 Parent 类中书写的先后顺序:
立即学习“Java免费学习笔记(深入)”;
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 先执行所有静态变量的显式赋值(如
static int x = getValue();) - 再执行每个
static {}块,按出现顺序依次运行 - 若某静态变量初始化依赖另一个静态变量,后者必须已声明在前(否则编译报错)
例如:static int a = 1; static int b = a + 1; 是合法的;而把 b 写在 a 前面则无法通过编译。
子类访问父类静态变量时的特殊情况
如果子类代码中直接引用的是父类的 public static final 编译期常量(如 public static final String NAME = "abc";),JVM 不会触发父类初始化。
因为该值已在编译阶段被内联进子类字节码,运行时不需加载父类。但只要访问的是非常量静态字段(哪怕只是读取 Parent.count),就必然触发 Parent 类完整静态初始化——包括所有静态变量赋值和所有 static 块。
常见误区澄清
父类静态变量不是“被子类继承后才初始化”,也不是“在子类构造器里才初始化”。它属于类本身,在类加载阶段就完成,与任何对象实例无关。即使你只写 Child.doSomething();(静态方法),且该方法完全没用到父类字段,只要 Child 类第一次被使用,Parent 的静态部分也早已执行完毕。

















