最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Java类加载和静态成员:代码块执行顺序的底层机理
时间:2026-06-20 09:58:52 编辑:袖梨 来源:一聚教程网
Java类初始化时静态成员按源码顺序交替执行,父类优先于子类;静态代码块在类首次主动使用时执行,编译期常量不触发初始化;new对象时先完成父子类静态初始化,再执行实例化流程。
Java 类加载过程中,静态成员的执行顺序不是随意安排的,而是由 JVM 类加载机制严格规定的初始化阶段决定的。核心在于:类初始化只发生一次,且静态代码块和静态变量赋值按源码顺序交替执行,父类优先于子类。
静态代码块何时真正执行
静态代码块在类的「初始化阶段」执行,前提是该类尚未初始化,且被首次主动使用。所谓“主动使用”包括:
- 访问某个静态字段(非编译期常量)
- 调用某个静态方法
- 对类进行 new 实例操作
- 反射调用 Class.forName("X")(默认 initialize=true)
注意:ClassLoader.loadClass("X") 不会触发初始化;而 static final 基本类型常量(如 public static final int PORT = 8080)属于编译期常量,直接内联,不触发类初始化,也就跳过静态代码块。
静态成员执行的真实顺序
同一类中,静态变量显式赋值(static int a = getValue();)和静态代码块(static { ... })按源码书写顺序从上到下交替执行,不是“先全赋值、再全执行块”。例如:
立即学习“Java免费学习笔记(深入)”;
- 若先写
static int x = f1();,后写static { y = f2(); },则f1()先调用 - 若
f1()中访问了后面才声明的static String z,此时z还未初始化,值为null或默认值(如 0),不会报编译错误,但可能引发逻辑异常 - 多个静态块之间也严格按定义顺序执行,无法靠位置覆盖前序逻辑
父子类之间的加载依赖关系
子类初始化必然触发父类初始化,但反过来不成立。具体表现为:
- 执行
Child.staticMethod()→ 先加载并初始化Parent(执行其全部静态成员),再初始化Child - 仅访问
Parent.STATIC_FIELD→ 只初始化Parent,Child完全不参与 - 父类静态初始化失败(如抛出
ExceptionInInitializerError)→ 整个类进入“初始化失败”状态,后续任何主动使用都会直接抛出同一异常
实例创建时的完整执行链条
当执行 new Child(),整个流程分两层展开:
- 类初始化层(仅一次):Parent 静态变量赋值 → Parent 静态块 → Child 静态变量赋值 → Child 静态块
- 对象实例化层(每次 new):Parent 实例变量赋值 & 实例块 → Parent 构造器 → Child 实例变量赋值 & 实例块 → Child 构造器
其中,实例块(即构造块 { ... })每次都在对应构造器体之前执行,属于对象级初始化,与静态内容完全隔离。
相关文章
- 2026年Notion AI设计场景用法:草稿生成与风格约束说明 06-20
- 京东在哪里可以解绑银行卡 06-20
- 2026年Notion AI响应缓慢:网络、缓存与账户配置排查 06-20
- 2026年Notion AI团队协作:权限、工作流与配置要点 06-20
- Notion AI企业版新手入门:账号权限与工作空间配置说明 06-20
- 如何用python创建项目 06-20