发布于2026-06-24 阅读(0)
扫一扫,手机访问
Ja va 代码块的执行顺序,很多人靠死记硬背口诀,但说到底,它不是什么玄学,而是由 JVM 类加载和对象创建这两个阶段联手决定的。关键就两点:搞清“类初始化”和“对象初始化”的区别——前者一辈子只干一次,后者每次 new 都来一遍;而不管是哪个阶段,执行顺序都受到继承关系和声明位置的严格约束。

静态代码块(static {})本质上是类级别的初始化代码。它什么时候跑?只有当这个类第一次被主动使用时——比如调静态方法、访问非 final 的静态字段、或者 new 它的实例——才会被触发。静态代码块和静态变量的显式赋值会被编译器打包进 方法,完全按照源码从上到下的顺序执行。
new Child(),也会先把 Parent 类加载并初始化完。public static final int X = 1;)不触发类初始化,因为它们直接被内联到调用处了,跟懒加载无关。static A a = new A();),就会提前进入对象初始化流程,而此时类的静态初始化还没走完。这种循环依赖容易导致字段读到默认值,属于经典坑点。不带 static 的普通代码块({})属于实例初始化,每次调用构造器之前都会自动运行。它的执行时机在实例变量显式赋值之后、构造方法体之前。因为对所有构造器都生效,很适合提取那些每个构造器都要做的公共初始化逻辑。
String name = "default";)处于同一层级,谁先谁后完全取决于它们出现的源码位置。创建子类对象时,JVM 会按照一条固定链条推进,不可跳过、不可倒置:
这里有个关键点:父类构造器执行的时候,子类所有的实例字段都还是默认值(0、null、false)。如果父类构造器中不小心调用了被子类重写的方法,而那个方法又访问了子类字段,就会读到未初始化的状态——这是多态在构造阶段最常见的“翻车”场景。
写在类中、方法外的 {} 是实例初始化块,参与对象的创建流程;而写在方法内部的 {} 只是局部作用域块,只在方法执行到那一行时才运行,跟对象初始化没有半毛钱关系。
{} 不影响字段初始化,也不改变执行顺序,顶多用来限制变量的生命周期或提升代码可读性。[I] init block、[C] ctor),跑一次就能看到类加载、对象创建、方法调用三条线是怎么交错进行的。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8