# 一.实验测试
# 1.final static 修饰
public class Apple01 {
static Apple01 apple = new Apple01(10);
final static double price = 20;
double result = 10;
public Apple01(double discount) {
System.out.println("price=" + price);
System.out.println("result=" + result);
result = price - discount;
System.out.println("result===" + result);
}
public static void main(String[] args) {
Apple01 apple1 = Apple01.apple;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
price=20.0 result=10.0 result===10.0
从执行结果可以看出,执行 apple 静态变量的时候, final static 修饰的 price 已经赋值为 20 了
# 2.仅 static 修饰
package com.xiaofei.antjvm.demo.base;
public class Apple01 {
static Apple01 apple = new Apple01(10);
static double price = 20;
double result = 10;
public Apple01(double discount) {
System.out.println("price=" + price);
System.out.println("result=" + result);
result = price - discount;
System.out.println("result===" + result);
}
public static void main(String[] args) {
Apple01 apple1 = Apple01.apple;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
price=0.0 result=10.0 result===-10.0
从执行结果可以看出,答案是-10,还是比较差异的,主要是执行 apple 静态变量的时候 price 的初始值还是 0
# 3.调整下顺序
public class Apple02 {
static double price = 20;
double result = 10;
static Apple02 apple = new Apple02(10);
public Apple02(double discount) {
System.out.println("price=" + price);
System.out.println("result=" + result);
result = price - discount;
System.out.println("result===" + result);
}
public static void main(String[] args) {
Apple02 apple1 = Apple02.apple;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
price=20.0 result=10.0 result===10.0
从执行结果可以看出,static 修饰的 price 和 apple 级别都是静态变量,谁在前面谁先执行
# 4.仅 final 修饰
public class Apple03 {
static double price = 20;
final static double price1 = 20;
final double price2 = 20;
double result = 10;
static Apple03 apple = new Apple03(10);
static double price3 = 20;
double result1 = 10;
final double price4 = 20;
public Apple03(double discount) {
System.out.println("price=" + price);
System.out.println("price1=" + price1);
System.out.println("price2=" + price2);
System.out.println("price3=" + price3);
System.out.println("price4=" + price4);
System.out.println("result=" + result);
System.out.println("result1=" + result1);
result = price - discount;
System.out.println("result===" + result);
}
public static void main(String[] args) {
Apple03 apple1 = Apple03.apple;
}
}
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
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
price=20.0 price1=20.0 price2=20.0 price3=0.0 price4=20.0 result=10.0 result1=10.0 result===10.0
从执行结果可以看到,在执行构造方法之前,会先执行非 static 方法(final 修饰的变量和普通变量,同等级)
# 二.测试总结
# 1.详细总结
- 当类被加载时,会首先执行静态代码块和静态变量的初始化。静态代码块和静态变量的执行顺序只跟代码中出现的顺序有关,且静态变量或静态方法中如果调用构造方法,可以把构造当做一个普通方法来看,但会先执行一遍代码块。
- 接着,会执行父类的静态代码块和静态变量初始化。
- 然后,执行子类的静态代码块和静态变量初始化,
- 实例化父类时,会先执行父类的实例变量初始化,然后执行父类的构造方法
- 实例化子类时,会先执行子类的实例变量初始化,然后执行子类的构造方法
- 在构造方法执行之前,会先执行非静态代码块。每被实例化一次,就会被执行一次。
- 最后,执行构造方法。如果构造方法体的第一行是 this 语句,则会调用相应的 this 语句所指的构造方法。如果构造方法体的第一行是 super 语句,则会调用相应的父类的构造方法。如果构造方法体的第一行既不是 this 语句也不是 super 语句,则会隐式调用 super(),即其父类的默认构造方法。
# 2.精简总结
- 类加载时,执行静态代码块和初始化静态变量。执行顺序跟代码顺序一致。
- 类实例化时,初始化变量、执行代码块、执行构造。其中初始化变量和代码块的顺序跟代码顺序一致。执行构造是在最后。
- 实例化子类时,会先调用父类的构造方法。调用构造方法之前,会先执行该类的代码块。
- 类只会加载一次。
- 静态变量或静态方法中如果调用构造,可以把构造当做一个普通方法来看。但会先执行一遍代码块