java中多个静态代码块按源码文本顺序依次执行且仅一次,与静态变量初始化混合排序;类初始化时先父类后子类;jvm保证多线程下仅执行一次并同步可见。

Java 中多个静态代码块会按照它们在类中出现的**文本顺序**依次执行,且只执行一次。
静态代码块的执行时机
静态代码块在类被首次主动使用(如创建实例、访问静态成员、反射加载等)而触发类加载和初始化阶段时执行。此时 JVM 会按源码中从上到下的顺序,逐个执行所有静态代码块和静态变量赋值语句(二者混合排序,统一按声明顺序处理)。
- 静态变量初始化和静态代码块属于“类初始化”阶段,统称 static initialization
- JVM 将它们视为一个整体,按源码书写顺序合并执行——先出现的先执行,后出现的后执行
- 即使静态代码块之间隔着静态字段声明,顺序依然严格遵循代码位置
静态代码块与静态变量初始化的混合顺序
静态变量赋值语句(含显式初始化)和静态代码块共享同一执行序列,JVM 按照它们在类体中出现的先后顺序依次执行。
例如:
static int a = 1; // 第1步
static { System.out.println("A"); } // 第2步
static int b = getValue(); // 第3步(调用方法)
static { System.out.println("B"); } // 第4步
static int getValue() { return 2; }
}
输出为:
A
B
因为 a = 1 和第一个静态块紧邻且靠前,b = getValue() 在第二个静态块之前,但它的执行仍排在第3位,而第二个静态块排第4位。
子类与父类的静态初始化顺序
若存在继承关系,JVM 会先完成父类的全部静态初始化(包括静态变量和静态块),再执行子类的静态初始化。
- 这是单向的:父类 → 子类
- 与实例初始化(构造器)不同,静态初始化不涉及“super()”调用,而是由类加载器保证依赖顺序
- 即使子类未显式引用父类静态成员,只要子类被初始化,父类必先完成静态初始化
注意:静态代码块不参与多线程竞争控制
类初始化是 JVM 级别的同步过程,保证多线程环境下静态代码块最多执行一次,且对所有线程可见。
- 无需手动加锁或使用 volatile
- 第一个触发类初始化的线程执行全部静态初始化;其余线程阻塞等待,之后直接使用已初始化状态
- 这也是实现单例(如静态内部类方式)的底层依据
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











