- 静态代码块:在类初始化时执行一次,在静态变量初始化之后。
- 实例代码块:在创建实例时,在构造函数之前执行。
- 构造函数:在实例代码块之后执行,用于初始化实例对象。
类加载过程中,代码块的执行顺序是一个重要的知识点。以下是详细的过程:
类加载的整体流程回顾
- 加载(Loading)
- 通过类的全限定名获取定义此类的二进制字节流。
- 将字节流所代表的静态存储结构转化为方法区的运行时数据结构。
- 在内存中生成一个代表这个类的
java.lang.Class
对象,作为方法区这个类的各种数据的访问入口。
- 验证(Verification)
- 确保被加载的类的字节码符合 Java 虚拟机规范,包括文件格式验证、元数据验证、字节码验证和符号引用验证等。
- 准备(Preparation)
- 为类的静态变量分配内存并设置默认初始值(例如
int
类型为 0,boolean
类型为false
等),但不执行初始化语句。
- 为类的静态变量分配内存并设置默认初始值(例如
- 解析(Resolution)
- 将常量池中的符号引用转换为直接引用。
- 初始化(Initialization)
- 执行类的初始化语句,包括静态变量的赋值语句和静态代码块。
- 执行类的初始化语句,包括静态变量的赋值语句和静态代码块。
代码块执行顺序
- 静态代码块
- 在类加载的初始化阶段,如果存在静态代码块,它会在静态变量初始化之后执行。
- 静态代码块只会执行一次,因为类只加载一次。例如
public class MyClass {
private static int num;
static {
num = 10;
System.out.println("静态代码块执行,num被赋值为10");
}
}
实例代码块
- 实例代码块在创建类的实例时执行。
- 它在构造函数之前执行。例如:
public class MyClass {
private int num;
{
num = 20;
System.out.println("实例代码块执行,num被赋值为20");
}
public MyClass() {
System.out.println("构造函数执行");
}
}
- 当创建
MyClass
的实例时,会先执行实例代码块,再执行构造函数。
- 构造函数
- 构造函数用于初始化类的实例对象。
- 在实例代码块之后执行(如果有实例代码块的话)。它负责对实例变量进行最终的初始化操作,并执行一些与实例对象相关的逻辑。
所以,类加载过程中代码块的执行顺序是:静态代码块(在类初始化阶段执行一次),然后在创建实例时,先执行实例代码块,再执行构造函数。