baeldung 2025-10-15
1. 概述
在本教程中,我们将学习 静态代码块(static block) 和 实例初始化块(instance initializer block) 的概念。我们还将探讨类构造函数与初始化块之间的区别及其执行顺序。
2. 静态代码块(Static Block)
在 Java 中,静态代码块用于在对象初始化之前执行代码。它是一个带有 static 关键字的代码块:
static {
// 静态代码块的定义
}
静态代码块也被称为 静态初始化块 或 静态子句。
该代码块仅在类加载时执行一次。由于编译器在类加载阶段就将静态代码块载入内存,因此静态代码块总是在 main() 方法之前执行。
一个类可以包含多个静态代码块,它们会按照在类中出现的顺序依次执行:
public class StaticBlockExample {
static {
System.out.println("static block 1");
}
static {
System.out.println("static block 2");
}
public static void main(String[] args) {
System.out.println("Main Method");
}
}
上述代码的输出为:
static block 1
static block 2
Main Method
在此示例中,编译器首先执行所有静态代码块,然后才调用 main() 方法。Java 编译器确保静态初始化块的执行顺序与其在源代码中的出现顺序一致。
此外,父类的静态代码块会先于子类执行,因为编译器在加载子类之前会先加载父类。
小知识:在 Java 1.7 之前,每个 Java 应用程序并不强制要求包含
main()方法,所有代码都可以写在静态代码块中。但从 Java 1.7 开始,main()方法成为必需。
3. 实例初始化块(Instance Initializer Block)
顾名思义,实例初始化块用于初始化实例成员变量。
它的语法与静态初始化块类似,但不使用 static 关键字:
{
// 实例初始化块的定义
}
由于静态代码块在类加载时执行,而实例初始化块在创建对象实例时执行,因此静态代码块总是先于实例初始化块执行。
Java 编译器会将实例初始化块的代码复制到每一个构造函数中。因此,多个构造函数可以通过这种方式共享同一段初始化代码:
public class InstanceBlockExample {
{
System.out.println("Instance initializer block 1");
}
{
System.out.println("Instance initializer block 2");
}
public InstanceBlockExample() {
System.out.println("Class constructor");
}
public static void main(String[] args) {
InstanceBlockExample iib = new InstanceBlockExample();
System.out.println("Main Method");
}
}
上述代码的输出为:
Instance initializer block 1
Instance initializer block 2
Class constructor
Main Method
每次调用构造函数创建对象时,实例初始化块都会被执行,因为编译器已将其内容嵌入到构造函数中。
此外,父类的实例初始化块会在当前类的实例初始化块之前执行。这是因为编译器通过 super() 调用父类构造函数,而实例初始化块正是在构造函数调用过程中执行的。
4. 静态代码块 vs 实例初始化块的区别
| 特性 | 静态代码块(Static Block) | 实例初始化块(Instance Initializer Block) |
|---|---|---|
| 执行时机 | 类加载时 | 创建类实例时(对象实例化) |
| 可访问变量 | 仅能访问静态变量 | 可访问静态变量和非静态(实例)变量 |
是否可使用 this |
❌ 不可以 | ✅ 可以 |
| 执行次数 | 整个程序运行期间仅执行一次 | 每次调用构造函数时都会执行 |
5. 总结
在本教程中,我们了解到:
- 静态代码块在类加载时执行,常用于初始化静态变量或调用静态方法;
- 实例初始化块在每次创建对象时执行,适用于初始化实例成员变量;
- 静态代码块先于实例初始化块执行;
- 多个静态/实例初始化块按其在源码中的顺序执行;
- 编译器会自动将实例初始化块插入到所有构造函数中,实现代码复用。
掌握这两类初始化块的使用场景和执行机制,有助于编写更灵活、可维护的 Java 代码。