Java继承场景下静态代码块与实例初始化块执行顺序问题
Java静态/实例代码块执行顺序规则说明
核心误区说明
你代码中标注为Static Block 2、Static Block 4的两个代码块没有加static修饰符,不属于静态代码块,是绑定到对象创建流程的实例构造代码块,二者执行时机完全不同,这就是你观察到Static Block 3先于Static Block 2执行的根本原因。
固定执行顺序规则
Java中类的初始化、对象创建流程在继承场景下遵循严格的先后顺序,整体分为两大阶段:
第一阶段:类加载初始化阶段(仅执行1次,类第一次被主动调用时触发)
这个阶段只执行静态相关逻辑,顺序为:
- 先执行父类的静态变量赋值、父类静态代码块(按代码编写的先后顺序执行)
- 父类静态逻辑全部执行完成后,再执行子类的静态变量赋值、子类静态代码块(按代码编写的先后顺序执行)
第二阶段:对象实例化阶段(每次new新对象都会执行1次)
类加载全部完成后才会进入实例创建流程,顺序为:
- 先执行父类的实例变量赋值、父类实例构造代码块(按代码编写的先后顺序执行),之后执行父类构造方法
- 父类实例构造逻辑全部完成后,再执行子类的实例变量赋值、子类实例构造代码块(按代码编写的先后顺序执行),之后执行子类构造方法
代码执行流程逐段拆解
测试代码如下:
class X{ static String a = "ABC"; static { a = a + "123"; System.out.println("Static Block 1"); } { a = "ABC123"; System.out.println("Static Block 2"); // 无static修饰,属于实例构造代码块,不是静态块 } } class Y extends X{ static { a = a + "123ABC"; System.out.println("Static Block 3"); } { System.out.println("Static Block 4"); // 无static修饰,属于实例构造代码块,不是静态块 System.out.println(a); } } public class MainClass { public static void main(String[] args) { Y y = new Y(); } }
运行结果:
输出对应执行步骤:
- 执行
main方法触发new Y()时,JVM发现Y类未加载,且Y继承自X,优先加载X类 - X类加载阶段:先给静态变量
a赋值为"ABC",再执行X的静态代码块,a变为"ABC123",打印Static Block 1,X类加载完成 - 开始加载Y类:执行Y的静态代码块,
a变为"ABC123123ABC",打印Static Block 3,Y类加载完成(此阶段还未进入对象创建流程,两个实例构造块都不会执行) - 进入Y对象实例化流程,先构造父类X的实例部分:执行X的实例构造代码块,将
a重新赋值为"ABC123",打印Static Block 2,之后执行X的隐式无参构造 - 父类实例构造完成,开始构造Y自身的实例部分:执行Y的实例构造代码块,先打印
Static Block 4,再打印当前a的值"ABC123",之后执行Y的隐式无参构造,对象创建完成
内容的提问来源于stack exchange,提问作者Foody
相关产品推荐
相关产品推荐

