java中代码块是jvm初始化流程的关键执行单元:静态代码块(static{})在类加载时执行一次,用于初始化共享资源;非静态代码块({})在每次实例化时执行,位于构造器前、实例变量赋值后,用于对象级共用初始化。

Java 中代码块是初始化资源的关键手段,不是可有可无的写法,而是直接嵌入到 JVM 初始化流程里的执行单元。静态资源靠 static{} 一次性准备,非静态资源靠 {} 每次实例化时统一设置,二者都严格按源码顺序执行,且必须配合继承层级和触发时机来安排。
静态代码块:只跑一次,类加载时自动触发
静态代码块用于初始化所有对象共享的资源,比如连接池、配置项、单例实例等。它在类首次被主动使用(如 new 实例、调用静态方法、访问非 final 静态字段)时执行,且仅一次。
- 多个静态代码块按源码从上到下依次执行,和静态变量赋值语句混合排序——谁写在前面,谁先执行
- 只能访问 static 字段和方法,不能用 this、super 或任何非静态成员
- 父类的静态部分一定先于子类执行;哪怕只 new 子类,父类也会被提前加载并初始化
- 注意循环风险:若静态变量初始化中 new 了本类对象(如 static A a = new A();),会提前触发实例初始化,但此时类尚未完成静态初始化,可能导致字段为默认值(0/null)
非静态代码块:每次 new 都走一遍,构造器前统一执行
非静态代码块(也叫构造代码块)属于对象级别,适合放多个构造器共用的初始化逻辑,比如参数校验、资源预分配、异常捕获等。它在每个构造器的第一行(super() 或 this() 调用完成后)立即执行。
- 执行时机在“实例变量显式赋值”之后、“构造器方法体”之前,编译后实际被插入每个构造器开头
- 可访问 this、实例字段、实例方法,也能调用静态成员
- 多个非静态代码块同样按源码顺序执行;父类的非静态块一定先于子类执行
- 如果类有多个构造器,用非静态代码块比在每个构造器里重复写更简洁、不易遗漏
继承场景下的完整执行链条
当创建子类对象时,初始化不是简单线性执行,而是分阶段、跨类展开:
- 先完成父类静态变量 → 父类静态代码块 → 子类静态变量 → 子类静态代码块(全部只执行一次)
- 再进入对象创建:父类实例变量赋值 → 父类非静态代码块 → 父类构造器 → 子类实例变量赋值 → 子类非静态代码块 → 子类构造器
- 静态部分和实例部分完全隔离:静态块不会因 new 多次而重跑;非静态块也不会跨对象共享状态
常见误区与实用建议
写错位置或混淆类型,容易导致字段未初始化、空指针或逻辑错乱:
- 别在静态块里调用可能被子类重写的方法(如 init()),此时子类静态部分还没执行,可能读到 null 或 0
- final static 基本类型常量(如 public static final int VERSION = 1;)不触发类初始化,引用它不会执行任何 static 块
- 静态字段未被任何代码访问,JVM 可能跳过其初始化逻辑(包括关联的静态块),所以不要依赖“写了就一定执行”
- 非静态代码块里避免耗时操作或 I/O,因为它每次 new 都执行,影响性能
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











