Java 对象的初始化过程
在 Java 中,对象的创建和初始化是一个复杂的过程,由 类加载、内存分配、默认初始化、显示初始化、构造方法调用 等多个步骤组成。这个过程由 JVM(Java 虚拟机) 负责,确保对象在使用前被正确初始化。
1. Java 对象的创建与初始化步骤
Java 对象的创建和初始化大致经历以下 5 个主要步骤:
1️⃣ 类加载检查(Class Loading Check)
• 检查类是否已加载(如果类未加载,先执行类的加载过程)。
• 如果对象的 类尚未被加载,JVM 先加载类,并执行 静态变量和静态代码块 的初始化。
2️⃣ 内存分配(Memory Allocation)
• JVM 在 堆(Heap) 中为对象分配内存。
• 如果 开启 TLAB(Thread Local Allocation Buffer),小对象的内存分配会更快。
3️⃣ 默认初始化(Default Initialization)
• JVM 自动将实例变量赋默认值(如 int=0,boolean=false,对象类型 null)。
4️⃣ 显示初始化 & 构造方法执行(Explicit Initialization & Constructor Execution)
• 实例变量赋值(如果变量在定义时赋值,则按顺序执行)。
• 实例代码块 {} 执行(实例代码块优先于构造方法执行)。
• 构造方法执行(按继承链,从父类到子类执行)。
5️⃣ 返回对象引用(Return Object Reference)
• 对象创建完成,并返回引用给调用方。
2. Java 对象初始化的顺序
Java 对象初始化按照 父类 → 子类 的顺序执行,具体流程如下:
🔹 对象初始化的执行顺序
1️⃣ 父类的静态变量 & 静态代码块(按代码顺序执行,仅一次)
2️⃣ 子类的静态变量 & 静态代码块(按代码顺序执行,仅一次)
3️⃣ 父类的实例变量 & 实例代码块(按代码顺序执行)
4️⃣ 父类的构造方法
5️⃣ 子类的实例变量 & 实例代码块(按代码顺序执行)
6️⃣ 子类的构造方法
3. 示例代码
(1)对象的初始化过程
class Parent {
static int staticVar = 10;
int instanceVar = 20;
static { System.out.println("1. 父类静态代码块, staticVar = " + staticVar); }
{ System.out.println("2. 父类实例代码块, instanceVar = " + instanceVar); }
public Parent() {
System.out.println("3. 父类构造方法执行");
}
}
class Child extends Parent {
static int staticChildVar = 30;
int instanceChildVar = 40;
static { System.out.println("4. 子类静态代码块, staticChildVar = " + staticChildVar); }
{ System.out.println("5. 子类实例代码块, instanceChildVar = " + instanceChildVar); }
public Child() {
System.out.println("6. 子类构造方法执行");
}
}
public class Test {
public static void main(String[] args) {
System.out.println("---- 开始创建对象 ----");
Child c = new Child();
}
}
(2)输出结果
1. 父类静态代码块, staticVar = 10
4. 子类静态代码块, staticChildVar = 30
---- 开始创建对象 ----
2. 父类实例代码块, instanceVar = 20
3. 父类构造方法执行
5. 子类实例代码块, instanceChildVar = 40
6. 子类构造方法执行
(3)分析
📌 静态代码块(static {})在类加载时执行,且仅执行一次。
📌 实例代码块({})在对象创建时执行,且在构造方法 之前 执行。
📌 构造方法按继承顺序执行(先父类,后子类)。
4. Java 类的加载 & 初始化过程
在 Java 中,类的加载 和 对象的初始化 是两个不同的阶段。
🔹 类的加载过程
当 JVM 第一次 使用某个类时,类的加载过程会触发,主要分为 三个阶段:
1️⃣ 加载(Loading)
• 读取 .class 文件,并存入 方法区(Method Area)。
• 解析类的 常量池 和 字段信息。
2️⃣ 链接(Linking)(包括以下 3 个子阶段)
• 验证(Verification):检查 .class 文件的字节码格式是否正确。
• 准备(Preparation):为 静态变量 分配内存,并赋默认值(如 0, null, false)。
• 解析(Resolution):解析 符号引用(Symbolic Reference),将其替换为实际引用。
3️⃣ 初始化(Initialization)
• 执行 静态变量赋值 和 静态代码块(static {})。
5. 总结
(1)对象的初始化步骤
步骤
过程
1. 类加载检查
如果对象的类未加载,先加载类,执行静态变量 & 静态代码块
2. 分配内存
在 堆(Heap) 中分配空间
3. 默认初始化
变量赋默认值(int=0,boolean=false)
4. 显示初始化 & 构造方法
变量赋初始值 → 实例代码块 {} 执行 → 构造方法执行
5. 返回引用
对象创建完成,返回引用
(2)类的初始化顺序
步骤
先执行父类
再执行子类
静态变量 & 静态代码块
✅
✅
实例变量 & 实例代码块
✅
✅
构造方法
✅
✅
(3)对象创建的执行顺序
1️⃣ 类加载(如果未加载)
2️⃣ 静态变量和静态代码块(父类 → 子类)
3️⃣ 实例变量和实例代码块(父类 → 子类)
4️⃣ 构造方法(父类 → 子类)
5️⃣ 对象创建完成,返回引用
💡 总结:
• 类的加载 发生在 第一次使用类时(包括静态成员访问或对象创建)。
• 对象的初始化 发生在 每次 new 时,包括 内存分配、变量赋值、构造方法执行。
• 静态代码块 仅在类加载时执行一次,而 实例代码块 在 每次对象创建时 都执行。
这样,Java 对象的初始化过程就完整总结了! 🚀