Java类初始化顺序为:静态初始化→内存分配与默认值→父类实例初始化→子类实例初始化;其中实例变量赋值和构造代码块按源码文本顺序执行,且均在构造方法体之前、super()/this()调用之后。

Java中类的初始化顺序直接影响对象状态,尤其当构造代码块、成员变量赋值和构造方法混用时,容易出现意料之外的值。关键在于:成员变量的显式初始赋值和实例初始化块(构造代码块)按它们在类中声明的**文本顺序**执行,且都发生在构造方法体执行之前。
成员变量赋值与构造代码块的执行时机
这两者属于“实例初始化阶段”,在每次调用构造方法创建对象时触发,且严格按源码中从上到下的顺序执行。它们早于构造方法中的任何语句,但晚于静态初始化(static块和静态变量)。
- 字段声明处的初始值(如 int x = 10;)会被编译器拆解为一条赋值语句,插入到每个构造方法开头(但在super()或this()调用之后)
- 构造代码块(即用 { ... } 包裹的代码)同样被编译器“复制”进每个构造方法,位置紧随字段赋值之后、构造方法体之前
- 若存在多个构造代码块,它们按出现顺序依次执行
典型初始化流程(非继承场景)
以一个普通类为例,完整顺序如下:
- 执行父类静态变量赋值和静态代码块(仅首次加载类时)
- 执行本类静态变量赋值和静态代码块(仅首次加载类时)
- 为新对象分配内存,所有字段设为默认值(0、null、false)
- 执行父类实例变量赋值 → 父类构造代码块 → 父类构造方法体
- 执行本类实例变量赋值 → 本类构造代码块 → 本类构造方法体
注意:super() 或 this() 调用必须是构造方法的第一条语句,它会引发父类对应初始化流程;而字段赋值和构造代码块实际插在 super()/this() 调用完成之后、构造方法其余代码之前。
立即学习“Java免费学习笔记(深入)”;
继承环境下易混淆的细节
子类构造过程中,父类的字段赋值和构造代码块先于子类的同类型代码执行,但父类构造方法体中若调用被子类重写的方法,此时子类字段可能尚未初始化(仍为默认值),导致空指针或零值问题。
- 避免在父类构造方法中调用可被重写的方法
- 字段初始值若依赖复杂逻辑,优先使用构造代码块或私有辅助方法,而非直接在声明处赋值
- 调试时可通过在各处添加日志(如 System.out.println("init x"))直观验证执行顺序
实战小例子说明顺序
以下代码输出为:A init → B init → x=20 → y=10
class Parent {
{ System.out.println("A init"); } // 构造代码块1
int x = 20; // 字段赋值1
}
class Child extends Parent {
int y = 10; // 字段赋值2
{ System.out.println("B init"); } // 构造代码块2
}
new Child() 时,执行流为:Parent构造代码块 → Parent字段x赋值 → Child字段y赋值 → Child构造代码块。字段和块的相对位置决定先后,与是否继承无关。


















