java继承初始化顺序为:静态变量→静态块→实例变量→构造块→构造方法,遵循先父后子、先静态后实例规则;类加载时仅执行静态部分,创建实例时完整执行全部阶段。

Java 继承中的初始化顺序可以通过编写带日志输出的父子类代码直观验证,核心是观察:静态变量 → 静态块 → 实例变量 → 构造块 → 构造方法,且遵循“先父后子、先静态后实例”的规则。
1. 定义带打印的日志父类和子类
在每个关键位置插入 System.out.println,明确标识执行阶段和所属类:
class Parent {
static String staticField = log("Parent 静态字段初始化");
static { log("Parent 静态代码块"); }
String instanceField = log("Parent 实例字段初始化");
{ log("Parent 实例代码块"); }
Parent() { log("Parent 构造方法"); }
static String log(String msg) {
System.out.println(msg);
return msg;
}
}
class Child extends Parent {
static String staticField = log("Child 静态字段初始化");
static { log("Child 静态代码块"); }
String instanceField = log("Child 实例字段初始化");
{ log("Child 实例代码块"); }
Child() { log("Child 构造方法"); }
}
2. 编写测试主程序并观察输出
仅加载子类(不创建对象)或创建子类实例,对比两种情况:
-
只触发类加载(不 new):运行
Class.forName("Child")或访问Child.staticField,只会执行 从 Parent 到 Child 的所有静态部分,按声明顺序逐个执行(父类静态优先)。 -
创建子类实例(new Child()):会完整触发全部阶段,输出顺序严格为:
→ Parent 静态字段 → Parent 静态代码块 → Child 静态字段 → Child 静态代码块
→ Parent 实例字段 → Parent 实例代码块 → Parent 构造方法
→ Child 实例字段 → Child 实例代码块 → Child 构造方法
3. 关键细节验证点
用以下小改动可进一步确认机制:
- 把父类构造方法中加入
System.out.println("this: " + this.getClass().getSimpleName()),能看到即使在父类构造器里,this指向的仍是Child实例——说明子类实例已存在,只是尚未执行子类自己的构造逻辑。 - 在子类实例字段赋值中调用一个方法,该方法访问子类未初始化的字段(如
int x = getValue();),会得到默认值(0 / null),因为此时子类实例字段还未赋值——印证“字段初始化发生在构造器之前,但按继承链顺序进行”。 - 将某个实例字段设为
final并在构造器中赋值,它仍会在实例代码块之后、构造器之前被设为默认值,再由构造器覆盖——体现 final 字段的特殊生命周期。
4. 注意编译与运行时机的区别
静态内容只在类首次主动使用时加载一次;而每次 new 都会重新执行实例字段初始化和构造流程。可通过两次 new Child() 对比输出,发现静态部分不再重复,但实例相关部分各执行一遍。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











