Java初始化分“类初始化”和“对象初始化”两层:静态代码块在类首次主动使用时执行一次,按源码顺序;构造代码块每次new时执行,优先于构造方法体,按声明顺序;继承时先父后子、先静态后实例。

Java初始化过程不是“先执行A再执行B”这么简单,而是一套分阶段、有依赖、受继承和加载时机影响的机制。核心在于区分“类初始化”和“对象初始化”两个层面,它们各自有明确的触发条件和执行顺序。
静态代码块:类加载时只跑一次
静态代码块(static {})属于类级别初始化,由JVM在类首次被主动使用时触发——比如调用静态方法、访问静态字段、创建该类实例等。它和静态变量初始化一起构成“类初始化阶段”,按源码中从上到下的顺序执行,且整个生命周期只执行一次。
- 多个静态代码块会严格按书写顺序执行
- 静态代码块只能访问静态成员,不能用
this或调用实例方法 - 如果静态变量初始化表达式中new了本类对象(如
static A a = new A();),会提前触发对象初始化流程,但此时类尚未完成初始化,需特别注意循环依赖风险
构造代码块:每次new都走一遍
不带static的普通代码块({} )属于实例初始化,在每次调用构造方法前自动执行,优先于构造方法体本身。它对所有构造器一视同仁,适合放置多个构造器共用的初始化逻辑。
- 多个构造代码块也按源码顺序依次执行
- 可访问实例变量和方法,也能访问外部作用域的局部变量(若在方法内定义)
- 它和实例变量的显式初始化(如
int x = 10;)处于同一执行层级,同样按声明顺序执行
继承场景下的完整执行链
当存在父子类继承时,初始化顺序不是平铺直叙,而是逐层向上再向下展开:
立即学习“Java免费学习笔记(深入)”;
- 先执行
Object类的静态部分(通常不可见) - 然后是父类的静态变量 → 父类静态代码块(同级按顺序)
- 接着是子类的静态变量 → 子类静态代码块
- 之后进入对象创建阶段:父类实例变量 → 父类构造代码块 → 父类构造方法
- 最后是子类实例变量 → 子类构造代码块 → 子类构造方法
这个链条确保父类状态总在子类之前准备就绪,也解释了为什么在构造代码块里调用被子类重写的方法可能引发空指针或未预期行为——此时子类字段尚未初始化。
与构造方法的本质区别
构造代码块不是语法糖,它解决的是构造方法无法优雅覆盖的问题:
- 构造方法可重载、可传参,用于差异化初始化
- 构造代码块无参数、不可重载,专用于统一前置逻辑(如日志记录、资源预分配、字段默认值设置)
- 若把共用初始化代码复制到每个构造方法里,不仅冗余,还容易漏改;抽成构造代码块后,维护成本显著降低
真正写代码时,建议把“所有对象都要做的初始化”放进构造代码块,把“根据参数定制的行为”留在构造方法里——分工清晰,不易出错。


















