Java初始化顺序严格遵循JVM规范:静态块按源码顺序在类首次主动使用时执行一次,父类先于子类;实例块在每次new时插入构造方法开头,super()后执行;局部块仅限作用域管理,不参与初始化。

Java 中代码块执行顺序本身是 JVM 严格定义的,所谓“规范化初始化流程”,不是去改变它,而是按它的天然节奏组织逻辑:把该放静态的地方放静态,该归实例的归实例,让父类和子类各司其职,避免交叉干扰。
静态部分只做一次性准备
所有类级别初始化——驱动注册、配置加载、单例构建、常量校验——都应放在 static {} 块或 static 变量显式赋值 中。它们在类首次被主动使用时(如 new、调用 static 方法、访问非编译期常量字段)统一执行一次,按源码从上到下合并进 <clinit> 方法。
- 父类静态内容一定先于子类执行,且只跑一遍
- 多个 static 块之间若有依赖,声明顺序就是执行顺序
- 避免在静态块里调用可能被子类重写的方法,也不引用子类尚未初始化的静态字段
- final static 编译期常量(如
public static final int MAX = 100;)不触发类初始化,慎用于需运行时计算的场景
实例部分专注对象状态构建
每次 new 对象时真正要做的事——设置默认 ID、预分配轻量资源、记录创建时间、校验基础字段——适合放进 构造代码块({},无 static)。它会被编译器自动插入每个构造方法开头,在 super() 返回之后、构造体开始之前执行。
- 多个构造代码块按书写顺序依次运行,和成员变量直接赋值(如
String name = "guest";)地位等同 - this 已可用,但不能调用可能被子类重写的方法(此时子类字段还是默认值)
- 它不替代构造方法,而是与之分工:构造块管“共性”,构造方法管“个性”(如参数差异化处理)
父子类初始化必须分层推进
new 子类对象时,JVM 会拉出一条清晰的流水线:先确保父类静态就绪 → 再完成子类静态 → 接着父类实例初始化(变量默认值→赋值/实例块→构造体)→ 最后子类实例初始化。这条链不可跳过,也不可倒置。
立即学习“Java免费学习笔记(深入)”;
- 父类构造器执行时,子类所有实例字段仍为默认值(
0、null、false) - 若父类构造器中调用了被子类重写的方法,而该方法又读取了子类字段,结果必然是未初始化状态
- 设计上应让父类构造器只做基础初始化,复杂逻辑后移到
init()或 final 方法中
普通块仅作作用域管理,不参与初始化
写在方法内部的 { ... }(如 void run() { int x = 1; { int y = x * 2; } })纯粹是语法作用域工具,和类加载、对象创建完全无关。它随方法调用而执行,不被编译器特殊处理,也不影响任何初始化顺序。
- 可用于限制变量生命周期、配合 try-with-resources 提前释放资源
- 切勿把它和构造代码块混淆,二者既不竞争执行权,也不存在先后关系
- 想控制初始化时机?别指望局部块,得回到 static / 实例块 / 构造器三层结构里找位置


















