static静态代码块在类加载时自动执行且仅一次,用于全局初始化如配置加载、单例创建;按源码顺序执行,线程安全,但抛异常会导致noclassdeffounderror。

Static静态代码块在类加载时自动执行,适合做全局属性的初始化工作,比如配置加载、单例创建、常量预计算等。它只运行一次,且在类首次被主动使用前完成,是JVM保证线程安全的初始化时机。
静态代码块的执行时机与特点
静态代码块属于类级别,随类加载(ClassLoader.loadClass)进入方法区后、在任何对象实例化之前执行。只要该类被首次“主动使用”(如调用静态方法、访问静态字段、new 实例、反射获取Class对象等),JVM 就会触发初始化阶段,此时静态代码块和静态变量赋值按书写顺序依次执行。
- 多个静态代码块按从上到下的顺序执行
- 静态变量初始化语句(如 static String CONF = loadConfig();)和静态代码块混合时,也按源码顺序执行
- 即使没创建对象,只要触发类初始化,静态代码块就执行
- 子类初始化会先触发父类初始化(可能连带执行父类静态代码块)
典型应用场景:全局配置/资源预加载
例如读取配置文件、初始化连接池、设置系统级参数:
<font color="#666666"><strong>public class AppConfig {<br> public static final String DB_URL;<br> public static final int MAX_POOL_SIZE;<br> public static final Logger LOGGER;<br><br> static {<br> Properties props = new Properties();<br> try (InputStream is = AppConfig.class.getResourceAsStream("/app.properties")) {<br> props.load(is);<br> } catch (IOException e) {<br> throw new ExceptionInInitializerError("Failed to load config", e);<br> }<br> DB_URL = props.getProperty("db.url", "jdbc:h2:mem:test");<br> MAX_POOL_SIZE = Integer.parseInt(props.getProperty("pool.size", "10"));<br> LOGGER = LoggerFactory.getLogger(AppConfig.class);<br> LOGGER.info("AppConfig initialized with DB_URL={}", DB_URL);<br> }<br>}</strong></font>
这样后续任意地方访问 AppConfig.DB_URL 时,配置已就绪,无需重复加载或判空处理。
配合静态字段实现线程安全单例
利用静态代码块天然的类初始化锁(JVM 内部保证),可简洁实现懒汉式但线程安全的单例:
<font color="#666666"><strong>public class DatabaseManager {<br> public static final DatabaseManager INSTANCE;<br><br> static {<br> try {<br> INSTANCE = new DatabaseManager();<br> INSTANCE.initConnectionPool(); // 可能抛异常<br> } catch (Exception e) {<br> throw new ExceptionInInitializerError(e);<br> }<br> }<br><br> private DatabaseManager() {}<br><br> private void initConnectionPool() { /* ... */ }<br>}</strong></font>
INSTANCE 在类加载时即创建并初始化,调用方直接使用 DatabaseManager.INSTANCE 即可,无同步开销,也避免双重检查锁的复杂性。
注意事项与避坑点
- 静态代码块中若抛出未捕获异常(包括 ExceptionInInitializerError),会导致类初始化失败,后续对该类的所有引用都会抛 NoClassDefFoundError
- 避免在静态块中调用其他尚未初始化类的静态方法(易引发死锁或 ClassNotFoundException)
- 不要在静态块中依赖外部可变状态(如系统时间、环境变量突变),否则行为不可预测
- 调试时注意:IDE 可能因自动导入、代码分析提前触发类加载,导致静态块意外执行










