之前应聘笔试的时候,遇到过很多次,给出一段代码,里面有static静态变量,static代码块以及构造函数等,在它们初始化或者是代码块中设置打印log,然后问它们的打印顺序。再此之前一直不知道具体考察的是什么,好在现在终于知道了,考察的是程序的初始化过程。
那么程序的初始化过程是怎样的呢?main方法执行的时候,首先要去装载包含它的类(Beetle),然后发现Beetle有个父类Insect,就先去加载Insect类,因为Insect没有父类了,就不必继续加载类。这个时候会从根基础类(在这个例子中根基础类是Insect)开始执行static初始化。static初始化包括static修饰的成员变量以及静态代码块,两者初始化的顺序与它们定义的顺序一致。先执行父类的static初始化,接着是子类的static初始化。static初始化完成之后,main方法开始执行,然后是父类的构造函数,再接着是子类的构造函数。
来看下面的程序:
class Insect{
int i = 9;
int j;
//父类构造函数
Insect(){
prt("i ="+i+", j = "+j);
j = 39;
}
//父类静态变量
static int x1 = prt("static Insect.x1 initialized");
//父类静态代码块
static {
System.out.println("Insect static");
}
static int prt(String s){
System.out.println(s);
return 47;
}
}
class Beetle extends Insect{
//子类成员变量
int k = prt("Beetle.k initialized");
//子类静态代码块
static {
System.out.println("Beetle static");
}
//子类呢构造函数
Beetle(){
prt("k = "+k);
prt("j = "+j);
}
//子类静态成员变量
static int x2 = prt("static Beetle.x2 initialized");
//子类静态代码块
static int prt(String s){
System.out.println(s);
return 63;
}
public static void main(String[] args){
prt("Beetle constructor");
Beetle b = new Beetle();
}
}
执行结果:
如上,例子直接反应了程序的初始化过程。