代码块是java类成员初始化中不可或缺的关键环节,静态代码块负责类加载时一次性初始化静态成员,非静态代码块则在每次实例化前统一初始化实例变量,二者均按源码顺序执行,并与字段显式赋值、构造器共同构成严格时序的初始化链条。

代码块在Java类成员初始化中不是可选的“装饰”,而是明确参与赋值流程的关键环节。它不替代属性声明或构造器,但会嵌入到初始化链条里,和显式赋值、构造器共同构成完整的赋值时序。
静态代码块:只执行一次,负责类级初始化
静态代码块随类加载而执行,且仅一次,用于初始化静态成员(static字段)或执行一次性类准备逻辑。
- 多个静态代码块按源码中出现顺序依次执行
- 它能访问静态变量和静态方法,但不能用this、super,也不能直接调用非静态成员
- 静态变量的显式赋值(如static int x = 5;)和静态代码块本质等价——JVM将它们合并进
<clinit></clinit>方法,按书写顺序执行 - 未被引用的静态字段及其关联的初始化逻辑(包括赋值语句和所在静态块)可能被JVM跳过——如知识库示例中Demo.b和第二个静态块未输出,因b在main中未被访问
非静态代码块(构造块):每次创建对象都执行
非静态代码块在每次调用构造器前执行,用于统一初始化实例变量,位置灵活但效果稳定。
- 多个非静态代码块也严格按源码顺序执行
- 它可访问静态和非静态成员,包括调用实例方法、给实例字段赋值
- 其执行时机在“实例变量显式初始化”之后、“构造器主体”之前——准确说,是紧邻在构造器第一行代码之前(即使构造器里没写super(),隐式调用也已完成)
- 与构造器内赋值不同,构造块对所有构造路径生效,适合提取共用初始化逻辑
代码块与属性赋值的协作关系
属性本身有默认值(如int为0,引用为null),而代码块是“主动介入”的赋值阶段之一。
- 实例变量的显式初始化(如String name = "Tom";)和非静态代码块属于同一层级,按声明顺序交织执行
- 若某实例变量在非静态代码块中被赋值,又在构造器中再次赋值,后者会覆盖前者
- 注意依赖陷阱:如int a = method();出现在int b = 10;之前,而method()返回b,则a得到的是b的默认值0——因为字段按声明顺序初始化,b尚未走到赋值步骤
父子类场景下的代码块联动
继承关系下,代码块不是孤立运行,而是嵌入到更长的初始化链中,体现“由父及子、静态先行”原则。
- 先执行父类静态成员赋值 + 父类静态代码块(按顺序)
- 再执行子类静态成员赋值 + 子类静态代码块(按顺序)
- 接着创建对象时:父类实例变量显式初始化 → 父类非静态代码块 → 父类构造器 → 子类实例变量显式初始化 → 子类非静态代码块 → 子类构造器
- 任意一级的非静态代码块都可安全使用已初始化的父类实例字段(因父类构造流程已启动)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











