类成员属性、静态变量、静态块、普通块、构造方法的加载顺序。

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
package com.ubuntuvim.clazzinit;


/**
* 类初始化时静态语句、静态语句块,普通成员、构造器的加载顺序
* 1. 执行静态语句或静态块(都是静态语句按照代码顺序执行)
* 2. 执行构造块代码或者构造语句(没有使用static声明的普通语句块)
* 3. 执行构造器
*
* 如下程序执行结果是:3 4 1 2
* @Author: ubuntuvim
* @Date: 2020/8/30 下午10:04
*/
public class StaticBlockMemberLoadingSort {

// 普通代码块(构造块)
{
System.out.println("1");
}

// 构造器
public StaticBlockMemberLoadingSort() {
System.out.println("2");
}

// 静态语句块
static {
System.out.println("3");
}

// 静态语句
static private int a = f1();

private static int f1() {
System.out.println("4");
return 10;
}

public static void main(String[] args) {
// 实例化
StaticBlockMemberLoadingSort staticBlockMemberLoadingSort = new StaticBlockMemberLoadingSort();
}
}

执行结果:

1
3 4 1 2

一个很典型的面试题。

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package com.ubuntuvim.clazzinit;


/**
* 类初始化时静态语句、静态语句块,普通成员、构造器的加载顺序
* 1. 执行静态语句或静态块(都是静态语句按照代码顺序执行)
* 2. 执行构造块代码或者构造语句(没有使用static声明的普通语句块)
* 3. 执行构造器
*
* 如下程序执行结果是:2 3 a=110, b=0 1 4 120
* 原因如下:
* 按照前面描述的执行顺序,先执行静态语句(27行)。
* 这个静态语句比较特殊,它显式的调用了构造器,然后开始执行构造器,但是在执行构造器的时候,根据初始顺序需要先执行构造块,
* 所以就先执行了35行的构造块代码,就打印了2,此时构造器语句还没执行完,因为在51还有一行构造器语句,执行完a的赋值之后。
* 才执行构造器,打印3,再打印a=110, b=0。为何b是0,因为还没执行到,目前b只是在内存中分配了但是还没执行初始化所以值还是默认的0。
* 构造器方法执行完之后,27行静态语句才执行完毕。紧接着执行其他的静态语句。接下来的静态语句是27行的。打印1.
* 再接下来还有一行静态语句51行,执行b的赋值(此时b才赋值,所以前面打印b是0)至此静态语句执行完毕。
* 开始执行构造代码块。但是由于前面第一句静态语句已经显式执行过了构造块所以不需要再次执行。到此类初始化完成。
* 接着就是常规操作,开始执行f1()方法,打印4,
* 最后执行打印b语句,打印120
* @Author: ubuntuvim
* @Date: 2020/8/30 下午10:04
*/
public class StaticBlockMemberLoadingSort2 {

// 静态语句
static StaticBlockMemberLoadingSort2 staticBlockMemberLoadingSort2 = new StaticBlockMemberLoadingSort2();

// 静态语句块
static {
System.out.println("1");
}

// 构造块语句
{
System.out.println("2");
}

// 构造方法
public StaticBlockMemberLoadingSort2() {
System.out.println("3");
System.out.println("a = " + a + ", b = " + b);
}

// 静态方法
public static void f1() {
System.out.println("4");
}

// 普通成员属性,构造语句
int a = 110;

// 静态语句,静态属性
static int b = 120;

public static void main(String[] args) {
// 实例化的方式有4中
/*
1. 通过new关键字
2. 通过Class.forName()反射
3. 通过类的调用静态方法(本例就是)
4. 通过类的调用静态属性
*/
StaticBlockMemberLoadingSort2.f1();

// 类已经初始化过了,不会再次初始化,直接打印120
System.out.println(StaticBlockMemberLoadingSort2.b);

}
}

执行结果:

1
2    3    a=110, b=0  1    4     120