前言:

在面试时,下面这道题应该经常遇到;那大家看看这道题中运行Test4中main方法后,控制台的输出内容的顺序是什么样的呀?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 父类
public class Test3 {
static{
System.out.println("test3 static start;");
}

public Test3(){
System.out.println("test3 gouzao start;");
}
}


// 子类Test4的静态属性类
public class Test5 {
static {
System.out.println("test5 static start;");
}

public Test5(){
System.out.println("test5 gouazao start;");
}
}


// 子类
public class Test4 extends Test3{

static Test5 t5 = new Test5();

static {
System.out.println("test4 static start;");
}

public Test4() {
//super();
System.out.println("test4 gouzao start;");
}

// test方法
public static void main(String[] args) {
Test4 t4 = new Test4();
}
}

那我们运行上面子类Test4中的main方法,看看输出内容的顺序是怎样的?

1
2
3
4
5
6
7
8
// main方法运行结果

test3 static start;
test5 static start;
test5 gouazao start;
test4 static start;
test3 gouzao start;
test4 gouzao start;

大家得出的输出结果与上面的结果一样吗;不一样的话,也别桑心呀,我来带大家去一步步的解析这道题,让大家在面试的时候不在这道题上跌倒。

解析:

首先,大家需要知道几个知识点:
1、static 代码块的执行、static 属性的初始化都是在类加载的时候进行的;

2、在 new 对象时,需要先进行类加载,如果当前类有父类的话,先进行父类的类加载,再进行当前类的类加载。

3、类中的静态代码框的执行、静态属性初始化的执行是根据在类中书写的顺序来的;例如:Test4中的 t5 静态属性就是比静态代码框先执行的。

4、在 new 对象时,在类加载完后,就该执行构造方法了,如果当前类有父类的话,就需要先执行父类的构造方法。在这里,你需要知道一个在构造方法中使用到 super(); 方法,它就是进行父类构造方法的调用执行的,但是在无参构造方法中无需自己手动显示调用,JVM会在编译时将其加入进去;


根据上面的知识点,解析上面的面试题
1、在 Test4 中执行 main 方法时,首先需要进行 Test4 的类加载;

2、但是由于 Test4 有父类 Test3 ,所以先进行 Test3 的类加载;

3、在执行 Test3 的类加载时,会执行静态代码框,输出 ①" test3 static start; "

4、进行完父类的类加载后,执行自己 Test4 的类加载,在进行类加载时,首先执行静态属性 t5 的初始化;

5、进行 t5 初始化时,是进行的 new 对象,所以需要进行 Test5 的类加载,在进行类加载时,执行静态代码框,输出 ②" test5 static start; ";

6、进行完 Test5 的类加载后,就是执行 Test5 的构造方法来完成 t5 静态属性的初始化,输出 ③" test5 gouazao start; " ;

7、t5 静态属性初始化完成后,需要执行静态代码框,输出 ④"test4 static start;" ;

8、此时 Test4 的类加载完成,此时需要执行构造方法创建对象,但是在执行 Test4 的构造方法时,内部会被JVM内置 super();,它会先去调用父类的构造方法执行,所以会现输出 ⑤" test3 gouzao start; " ;最后才输出 ⑥" test4 gouzao start; "


谢谢大家阅读,鉴于本人水平有限,如有问题敬请提出。