一 结论
执行顺序:
| 顺序 | 执行内容 |
|---|---|
| 1 | 父类静态域 |
| 2 | 子类静态域 |
| 3 | 父类非静态域,构造函数 |
| 4 | 子类非静态域,构造函数 |
二 原因
2.1 类初始化
类初始化过程可以说是虚拟机执行类构造器<clinit>()方法的过程。下面是有关<clinit>()的相关说明:
<clinit>()是由编译器自动收集类中所有类变量的赋值动作和静态语句块中的语句合并产生的。
收集的顺序由语句在源文件中出现的顺序决定。因此,同一级别域的初始化语句的顺序由代码中书写顺序决定<clinit>()方法于构造函数的<init>()方法不同,前者是类构造器,后者是实例构造器。
不需要显示调用,虚拟机会保证在子父类的<clinit>()方法在子类的<clinit>()方法之前执行。因此,父类的静态域早于子类的静态域被初始化
2.2 类实例化
同上,类实例化的过程可以说是虚拟机执行实例构造器<init>()方法的过程。相关说明:
<init>()方法是由编译器收集类中语句块{}、实例变量等合并产生。收集的顺序由语句在源文件中出现的顺序决定。因此,同一级别域的初始化语句的顺序由代码中书写顺序决定- 子类的
<init>()方法中会首先对父类<init>()方法的调用。因此,父类的非静态域以及构造函数早于子类的非静态域和构造函数被执行
2.3 类初始化和类实例化的时机
类初始化阶段是在类加载过程中完成,类实例化则需要在类加载完成之后才能进行。因此,<clinit>()方法在<init>()方法之前执行