Java中的静态初始化块与实例初始化块
Java中的静态初始化块与实例初始化块
在本教程中,我们将学习静态块和实例初始化块的概念。我们还将检查类构造函数和初始化块的执行顺序及其差异。
在Java中,静态块在对象初始化前执行代码。静态块是带有_static_关键字的代码块:
static {
// 静态块的定义
}
静态初始化块或静态初始化子句还有其他一些名称,比如静态块。静态块代码仅在类加载期间执行一次。静态块总是在Java中的_main()_方法之前执行,因为编译器在类加载时将它们存储在内存中,并且在对象创建之前。
一个类可以有多个静态块,它们将按照在类中出现的顺序执行:
public class StaticBlockExample {
static {
System.out.println("静态块 1");
}
static {
System.out.println("静态块 2");
}
public static void main(String[] args) {
System.out.println("主方法");
}
}
上述代码片段的输出为:
静态块 1
静态块 2
主方法
在这里,编译器首先执行所有静态块,完成静态块执行后,调用_main()_方法。Java编译器确保静态初始化块的执行顺序与它们在源代码中出现的顺序相同。
父类的静态块首先执行,因为编译器在加载子类之前加载父类。
作为一个有趣的事实,Java 1.7之前,main()方法并不是每个Java应用程序中都必须的,所以所有代码都可以在静态块内编写。然而,从Java 1.7开始,main()方法是强制性的。
实例初始化块
顾名思义,实例初始化块的目的是初始化实例数据成员。
实例初始化块看起来就像静态初始化块,但没有_static_关键字:
{
// 实例初始化块的定义
}
静态初始化块总是在实例初始化块之前执行,因为静态块在类加载时运行。然而,实例块在实例创建时运行。Java编译器将初始化块复制到每个构造函数中。因此,多个构造函数可以使用这种方法共享一段代码:
public class InstanceBlockExample {
{
System.out.println("实例初始化块 1");
}
{
System.out.println("实例初始化块 2");
}
public InstanceBlockExample() {
System.out.println("类构造函数");
}
public static void main(String[] args) {
InstanceBlockExample iib = new InstanceBlockExample();
System.out.println("主方法");
}
}
在这种情况下,上述代码的输出将是:
实例初始化块 1
实例初始化块 2
类构造函数
主方法
实例初始化块在每次构造函数调用期间执行,因为编译器将初始化块复制到构造函数本身中。
编译器在执行当前类的实例块之前先执行父类的实例块。编译器通过_super()_调用父类构造函数,实例块在构造函数调用时执行。
静态块与实例初始化块之间的差异
| 静态块 | 实例初始化块 |
|---|---|
| 它在类加载期间执行 | 它在类实例化期间执行 |
| 它只能使用静态变量 | 它可以使用静态或非静态(实例变量) |
| 它不能使用this | 它可以使用this |
| 当类加载到内存时,它在整个程序执行期间只执行一次 | 每次调用构造函数时都可以运行多次 |
结论
在本教程中,我们了解到编译器在类加载期间执行静态块。静态块可用于初始化静态变量或调用静态方法。然而,实例块每次创建类的实例时都会执行,并且可用于初始化实例数据成员。
此外,本文的完整代码示例可以在GitHub上找到。