static修饰符不改变类加载器的加载行为,但决定类初始化阶段的执行顺序:首次主动使用类时触发初始化,父子类按继承顺序初始化静态成员,同一类中static变量与代码块按源码顺序执行且仅一次。

static 修饰符本身不改变类加载器的“加载”行为(即字节码文件何时被读入 JVM),但它直接决定类在 初始化阶段 的执行顺序——而这个初始化过程,正是类加载器触发并严格控制的关键环节。
static 成员触发类的初始化时机
Java 规范规定:当首次主动使用一个类时(如 new 实例、调用静态方法、访问静态字段、反射获取 Class 对象等),JVM 才会触发该类的初始化。此时,类加载器已完成“加载”和“链接”,真正开始执行 static 内容。
- 仅声明或引用类名(如 Class.forName("X", false, loader) 中第二个参数为 false)不会触发初始化
- 访问 final static 基本类型常量(如 public static final int MAX = 100;)属于编译期常量,也不会触发类初始化
- 但访问任意非编译期常量的 static 字段(哪怕只是读取 public static String MSG = "hello";),就会强制初始化该类
父子类之间的 static 初始化顺序
当子类首次被主动使用时,类加载器会确保父类先完成初始化。整个初始化流程严格按以下顺序执行:
- 父类的静态变量赋值语句(按代码中出现顺序)
- 父类的静态代码块(按定义顺序,与变量初始化交替执行)
- 子类的静态变量赋值语句
- 子类的静态代码块
注意:这个顺序是 JVM 初始化阶段的硬性规则,与类是否已被加载无关——只要父类尚未初始化,子类初始化就必须暂停等待父类完成。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
static 代码块与变量的执行顺序细节
同一类中,static 变量初始化和 static 代码块按源码书写顺序依次执行,且只执行一次:
- 例如:static int a = foo(); static { System.out.println("A"); } static int b = bar(); 会依次调用 foo() → 打印 "A" → 调用 bar()
- 若 static 变量初始化过程中抛出异常,该类初始化失败,后续任何对该类的主动使用都会抛出 ExceptionInInitializerError
- 静态内容执行期间,类处于“正在初始化”状态,其他线程对同一类的初始化请求会被阻塞,保证线程安全
static 不影响类加载器的委托机制
双亲委派模型(Parent Delegation Model)不受 static 影响:无论类中是否有 static 成员,类加载器仍按“子加载器先委托父加载器”的顺序尝试加载类字节码。static 只作用于“初始化”这最后一步,而非“加载”或“验证”阶段。
换句话说:类加载器决定“谁来加载这个类”,而 static 决定“加载后第一时间做什么”。两者职责分明,不可混淆。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










