在类的继承中,初始化的顺序决定着程序的输出。一般而言,类的代码在第一次使用时才加载。下面通过代码和输出分析类初始化顺序。
class GrandParent {
int i = 9;
int j;
static int x1 = prt("static GrandParent.x1 initialized");//注意这里是static字段
static{
<span style="white-space:pre"> </span>System.out.println("GrandParent");
}
GrandParent() {
prt("i = " + i + ", j = " + j);
j = 39;
}
static int prt(String s) {
<span style="white-space:pre"> </span>System.out.println(s);
return 30;
}
}
class Parent extends GrandParent {
static int x1 = prt("static Parent.x1 initialized");//注意这里是static字段
static{
<span style="white-space:pre"> </span>System.out.println("parent");
}
Parent() {
prt("i = " + i + ", j = " + j);
j = 55;
}
static int prt(String s) {
<span style="white-space:pre"> </span>System.out.println(s);
return 47;
}
}
public class Son extends Parent {
int k = prt("Son.k initialized");
static{
<span style="white-space:pre"> </span>System.out.println("son");
}
static int x1 = prt("static Son.x1 initialized");//注意这里是static字段
Son() {
prt("k = " + k + ", j = " + j);
}
static int prt(String s) {
System.out.println(s);
return 63;
}
public static void main(String[] args) {
prt("Son constructor");
Son s = new Son();
System.out.println(x1);
}
}
输出结果:
static GrandParent.x1 initialized
GrandParent
static Parent.x1 initialized
parent
son
static Son.x1 initialized
Son constructor
i = 9, j = 0
i = 9, j = 39
Son.k initialized
k = 63, j = 55
63
结果分析:
我们知道程序运行的入口是public static void main(String[] args)。存在static属性和static代码块时,先不执行main函数的第一条程序,而是进行static初始化。在初始化时,先初始化基类,再初始化子类。因此,static初始化(static属性和static代码块优先级相同,谁在前先初始化谁),按照基类到子类的顺序,得到前部分输出:
static GrandParent.x1 initialized
GrandParent
static Parent.x1 initialized
parent
son
static Son.x1 initialized
static初始化完成后,执行main函数的第一条程序 prt("Son constructor"),输出:
Son constructor
接着执行第二条程序Son s = new Son(),创建Son对象,Son的基类为Parent,Parent的基类为GrandParent,因此首先要完成GrandParent类的初始化,按照普通类初始化的顺序,先初始化属性,再初始化构造器(static已经在前面初始化了),完成GrandParent类的初始化得到输出:
i = 9, j = 0
同理,完成Parent类的初始化得到输出:
i = 9, j = 39
继续同理,完成Son类的初始化得到输出:
Son.k initialized
k = 63, j = 55
执行第三条程序System.out.println(x1),因为最后执行Son类的prt(String s)方法,返回值为63,所以输出:
63
Java继承类的初始化先后顺序总结:
先进行static初始化(static属性和static代码块谁在前先初始化谁),接着执行main方法中的程序,从上到下依次执行。执行到创建对象的语句时,先完成基类的初始化,此时将基类看成普通类,按照普通类的初始化原则(先初始化属性,再初始化构造器,因为static已经在前面初始化了),同理进行子类的初始化。
PS:想说清楚,说的有点啰嗦,希望大家谅解哈。