Java代码块执行顺序严格遵循JVM机制:1. 静态块在类首次主动使用时按源码顺序执行一次;2. 构造块每次new对象时在父类super()后、构造器体前执行;3. 父子类初始化先父后子、先静后动;4. 局部块仅限方法内作用域,不参与初始化。

Java代码块的执行顺序不是随意安排的,而是由JVM类加载和对象创建机制严格决定的。理解这个顺序,能帮你快速定位初始化问题、避免空指针或非法前向引用,也能写出更清晰的初始化逻辑。
静态代码块:类初始化时只跑一次
静态代码块(static{})在类首次被主动使用时触发,属于“类初始化阶段”,不是类加载瞬间就执行。常见触发场景包括:
• new 某个类的实例
• 调用该类的 public static 方法
• 访问非编译期常量的 public static 字段(如 public static int PORT = 8080;;但 public static final String MSG = "ok"; 不会触发)
• 反射调用 Class.forName("X")
多个静态块按源码从上到下顺序执行。一旦某个静态块抛出未捕获异常,整个类初始化失败,后续对该类的任何主动使用都会直接抛出 ExceptionInInitializerError。
构造代码块:每次new对象时自动插入构造器开头
构造代码块({},无static修饰)属于对象初始化的一部分,与类加载无关。它会在每次调用构造器前执行,准确位置是:
• 父类 super() 调用完成之后
• 本构造器方法体开始之前
编译器会把它“复制”到每个构造器的最开头,所以无论有多少个重载构造器,只要被调用,该块就执行一次。它可以安全访问静态成员和实例成员(前提是成员声明在它之前),适合抽取多个构造器共有的初始化逻辑。
父子类完整初始化顺序:先父后子,先静后动
当执行 new Child() 时,实际执行链为:
• 父类静态代码块 → 子类静态代码块(仅首次触发)
• 父类构造代码块 → 父类构造方法
• 子类构造代码块 → 子类构造方法
注意:静态块只走一遍;之后每次 new 都重复后四步。如果父类构造器里调用了可被子类重写的方法,要特别小心——此时子类字段可能尚未初始化(因子类构造代码块还没执行)。
立即学习“Java免费学习笔记(深入)”;
普通局部块:纯语法作用域,不参与初始化流程
写在方法内部的 { ... }(比如 void foo() { int x = 1; { System.out.println(x); } })既不属于类加载,也不属于对象创建。它只是限制变量作用域、提前释放资源或提升可读性的语法结构。
• 执行时机完全取决于方法是否被调用、执行流是否到达该位置
• 即使类从未初始化(比如只反射获取Class对象但没触发主动使用),只要方法被调用且走到这里,它就会运行
• 它和静态块、构造块没有先后依赖关系,只是普通语句序列中的一段


















