静态代码块在类首次主动使用时由jvm在初始化阶段执行且仅一次,按源码顺序与静态变量交错执行,父类优先于子类,不可用this或非静态成员,异常会导致类初始化失败。

静态代码块在类首次被主动使用时执行,且只运行一次——它不依赖对象创建,也不等构造方法,而是由JVM在类初始化阶段自动触发。
静态代码块的执行时机很明确
它只在类进入“初始化阶段”时运行,这个阶段发生在类第一次被主动使用时,比如:
- 调用该类的静态方法
- 访问非final static的静态字段(如
MyClass.value) - 用
new创建该类实例 - 反射调用
Class.forName("MyClass")(默认initialize=true)
注意:static final基本类型常量(如public static final int PORT = 8080;)属于编译期常量,引用它不会触发类初始化,也就跳过静态代码块。
静态代码块按源码顺序与静态变量交错执行
同一类中,静态变量显式赋值和static{}块不是“先全赋值、再全执行”,而是谁写在前面,谁先运行:
-
static int a = getValue();→ 立即执行getValue() - 紧接着遇到
static { b = compute(); }→ 立即执行该块 - 再遇到
static int c = a + 1;→ 此时a已是计算后的值
如果某个静态块里引用了后面才声明的静态变量,那个变量此时仍是默认值(如int为0,Object为null),不是编译错误,但结果可能不符合预期。
有继承关系时,父类静态部分一定先执行
哪怕你直接new Child(),JVM也会强制先完成Parent类的初始化:
- 父类静态变量默认值 → 父类静态变量赋值 + 静态块(从上到下)
- 子类静态变量默认值 → 子类静态变量赋值 + 静态块(从上到下)
整个过程只发生一次。后续再new子类、调用子类静态方法,都不会重复执行父类或子类的静态块。
静态代码块不能做的事要特别注意
它运行在类加载阶段,此时还没有任何实例,所以:
- 不能使用
this,也不能调用非静态方法或访问非静态字段 - 可以
new对象,但如果该对象构造过程中又间接触发本类其他静态初始化,可能引发循环依赖 - 一旦抛出未捕获异常(如
NullPointerException),类会进入“初始化失败”状态,之后所有对该类的主动使用都会直接抛NoClassDefFoundError
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











