### JAVA面试题解惑系列——类的初始化顺序
#### 一、基础知识回顾
在Java编程中,类的初始化顺序是一个非常重要的概念,特别是在面试时,它经常被用来考察面试者对于Java类加载机制的理解程度。类的初始化顺序涉及到类中的各种成员的加载顺序,包括静态变量、静态初始化块、实例变量、初始化块以及构造器等。
根据Java语言规范,初始化的顺序遵循以下原则:
1. **静态变量**和**静态初始化块**:首先加载的是类中的静态成员,包括静态变量和静态初始化块。这些成员只在类首次被加载时初始化一次。
2. **实例变量**和**初始化块**:接着是类中的非静态成员,即实例变量和非静态初始化块。这些成员在每次创建对象时都会被初始化。
3. **构造器**:最后执行的是构造器,用于完成对象的构建过程。
#### 二、单个类中的初始化顺序
为了更直观地理解这一顺序,我们可以通过下面的示例代码来进一步探讨:
```java
public class InitialOrderTest {
// 静态变量
public static String staticField = "静态变量";
// 变量
public String field = "变量";
// 静态初始化块
static {
System.out.println(staticField);
System.out.println("静态初始化块");
}
// 初始化块
{
System.out.println(field);
System.out.println("初始化块");
}
// 构造器
public InitialOrderTest() {
System.out.println("构造器");
}
public static void main(String[] args) {
new InitialOrderTest();
}
}
```
当运行这段代码时,控制台输出如下:
1. **静态变量**
2. **静态初始化块**
3. **变量**
4. **初始化块**
5. **构造器**
由此可见,静态成员(静态变量和静态初始化块)总是最先被初始化,随后是非静态成员(变量、初始化块),最后是构造器。
#### 三、继承情况下的初始化顺序
在Java中,类可以继承其他类。因此,在处理继承时,我们需要考虑父类和子类的初始化顺序。下面我们通过一个具体的例子来观察这个过程:
```java
class Parent {
// 静态变量
public static String p_StaticField = "父类--静态变量";
// 变量
public String p_Field = "父类--变量";
// 静态初始化块
static {
System.out.println(p_StaticField);
System.out.println("父类--静态初始化块");
}
// 初始化块
{
System.out.println(p_Field);
System.out.println("父类--初始化块");
}
// 构造器
public Parent() {
System.out.println("父类--构造器");
}
}
public class SubClass extends Parent {
// 静态变量
public static String s_StaticField = "子类--静态变量";
// 变量
public String s_Field = "子类--变量";
// 静态初始化块
static {
System.out.println(s_StaticField);
System.out.println("子类--静态初始化块");
}
// 初始化块
{
System.out.println(s_Field);
System.out.println("子类--初始化块");
}
// 构造器
public SubClass() {
System.out.println("子类--构造器");
}
public static void main(String[] args) {
new SubClass();
}
}
```
运行这段代码,控制台输出如下:
1. **父类--静态变量**
2. **父类--静态初始化块**
3. **子类--静态变量**
4. **子类--静态初始化块**
5. **父类--变量**
6. **父类--初始化块**
7. **父类--构造器**
8. **子类--变量**
9. **子类--初始化块**
10. **子类--构造器**
从输出结果可以看出,在继承的情况下,静态成员(包括静态变量和静态初始化块)按照定义的顺序初始化。父类的非静态成员(变量、初始化块和构造器)先于子类的非静态成员初始化。
#### 四、静态变量与静态初始化块的顺序
在单个类中,静态变量和静态初始化块之间的初始化顺序取决于它们在类中的声明顺序。如果静态变量出现在静态初始化块之前,则静态变量先被初始化;反之亦然。例如:
```java
public class TestOrder {
// 静态变量
public static String staticVar = "静态变量";
// 静态初始化块
static {
System.out.println(staticVar);
System.out.println("静态初始化块");
}
}
```
在这个例子中,因为静态变量`staticVar`位于静态初始化块之前,所以静态变量先于静态初始化块被初始化。
总结来说,在Java中,类的初始化顺序是非常关键的知识点之一,特别是对于面试准备来说。掌握这些基本规则有助于更好地理解和编写Java程序。