java静态代码块在类初始化阶段执行且仅一次,不参与类加载;触发条件包括new实例、访问静态字段、调用静态方法等;按源码顺序执行,不可访问实例成员,避免耗时操作和未捕获异常。

Java静态代码块不是“被加载”,而是随着类的初始化阶段自动执行——它本身不参与类加载(Loading),只在类初始化(Initialization)时触发,且仅一次。
静态代码块到底什么时候执行
它发生在JVM对类进行“初始化”阶段,前提是该类已被加载(Loading)和验证(Verification),但尚未初始化。触发初始化的常见动作包括:
- 使用
new创建该类的第一个实例 - 访问该类的静态字段(非
final常量,或首次读写) - 调用该类的静态方法
- 反射调用
Class.forName("ClassName")(默认initialize=true) - JVM启动时,直接运行包含
main方法的主类
注意:仅获取Class对象(如Singleton.class)不会触发初始化,也就不会执行静态代码块。
静态代码块与类加载器的关系
类加载器(Bootstrap、Extension、Application)负责把字节码从文件或网络读入内存(即Loading阶段),但不执行静态代码块。真正执行静态代码块的是JVM在初始化阶段的行为,与哪个类加载器加载无关——只要类完成加载并首次被主动使用,就会进入初始化,静态代码块随之运行。
自定义类加载器若重写loadClass()但未调用defineClass(),或显式传入false跳过resolve,也不会触发初始化;只有调用Class.forName(name, true, loader)才确保初始化。
多个静态代码块的执行顺序
同一类中,多个static{}块按源码中从上到下的顺序依次执行,且全部执行完才允许后续静态变量赋值或静态方法调用。
例如:
static { System.out.println("1"); }private static final String A = "hello";
static { System.out.println("2"); }
输出一定是:1 → 2,即使A声明在中间。
典型误用与避坑提醒
- 别在静态代码块里做耗时操作(如远程HTTP请求、大文件IO),会阻塞整个类初始化,影响所有后续调用
- 避免在静态块中抛出未捕获异常——会导致
NoClassDefFoundError,且该类后续永远不可用 - 不能访问实例成员(
this、非static字段/方法),编译直接报错 - 想延迟初始化?静态代码块不适合——它天生是“饿汉式”。改用静态内部类或
Supplier+ 双重检查锁
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











