一.回顾类的运行期常量
-
类的静态常量:public static final
-
当MyTest类的方法调用MyChild中运行期常量时就需要初始化MyChild类及其所有父类
-
当MyTest类的方法调用MyChild中编译期常量时不需要初始化MyChild类及其所有父类,由于编译期常量被放在MyTest类的常量池中了
-
类的静态变量:public static
-
当MyTest类的方法中调用子类名.父类静态变量,会初始化父类,不会初始化子类
-
当MyTest类的方法中调用子类名.子类静态变量,会初始化父类和子类
二.分析接口
-
由于接口中的属性默认为public static final,则默认为静态常量。则和类的静态常量的运行期和编译期一模一样。
三.例题分析
结论:静态变量初始化顺序从上到下依次进行
(1)案例一
1 public class MyTest5 {
2
3 public static void main(String[] args) {
4 Singleton singleton = Singleton.getInstance();
5
6 System.out.println("counter1: "+Singleton.counter1);
7 System.out.println("counter2: "+Singleton.counter2);
8 }
9 }
10
11 class Singleton {
12 public static int counter1;
13
14 public static int counter2 = 0;
15
16 private static Singleton singleton = new Singleton();
17
18 private Singleton(){
19 counter1++;
20 counter2++;
21 }
22
23 public static Singleton getInstance(){
24 return singleton;
25 }
26 }
27
28 /*
29 * 输出:
30 * counter1: 1
31 * counter2: 1
32 * */
分析初始化过程:
-
调用getInstance方法返回singleton,此时调用初始化过程
-
准备阶段:代码从上往下先进行静态变量赋默认值,counter1 = 0,counter2 = 0,singleton = null
-
初始化阶段:counter2 = 0,singletton调用私有构造函数得counter1 = 1,counter2 = 1
-
结果为counter1 = 1,counter2 = 1
(2)案例二
案例二只是将案例一中的 public static int counter2 = 0; 位置改变了。
1 public class MyTest5 {
2
3 public static void main(String[] args) {
4 Singleton singleton = Singleton.getInstance();
5
6 System.out.println("counter1: "+Singleton.counter1);
7 System.out.println("counter2: "+Singleton.counter2);
8 }
9 }
10
11 class Singleton {
12 public static int counter1;
13
14 private static Singleton singleton = new Singleton();
15
16 private Singleton(){
17 counter1++;
18 counter2++;
19 }
20
21 public static int counter2 = 0;
22
23 public static Singleton getInstance(){
24 return singleton;
25 }
26 }
27
28 /*
29 * 输出:
30 * counter1: 1
31 * counter2: 0
32 * */
分析初始化过程:
-
调用getInstance方法返回singleton,此时调用初始化过程
-
准备阶段:代码从上往下先进行静态变量赋默认值,counter1 = 0,singleton = null,counter2 = 0
-
初始化阶段:singletton调用私有构造函数得counter1 = 1,counter2 = 1,再counter2 = 0
-
结果为counter1 = 1,counter2 = 0