3.JVM的借口初始化规则与类加载器准备阶段和初始化阶段的重要意义分析

一.回顾类的运行期常量

  • 类的静态常量: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 * */

分析初始化过程:

  1. 调用getInstance方法返回singleton,此时调用初始化过程

  2. 准备阶段:代码从上往下先进行静态变量赋默认值,counter1 = 0,counter2 = 0,singleton = null

  3. 初始化阶段:counter2 = 0,singletton调用私有构造函数得counter1 = 1,counter2 = 1

  4. 结果为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 * */

分析初始化过程:

  1. 调用getInstance方法返回singleton,此时调用初始化过程

  2. 准备阶段:代码从上往下先进行静态变量赋默认值,counter1 = 0,singleton = null,counter2 = 0

  3. 初始化阶段:singletton调用私有构造函数得counter1 = 1,counter2 = 1,再counter2 = 0

  4. 结果为counter1 = 1,counter2 = 0

猜你喜欢

转载自www.cnblogs.com/zhihaospace/p/12293193.html