天天看點

七、接口初始化規則與類加載器準備階段和初始化階段的重要意義分析

1、接口初始化規則

已知:

1、靜态常量分為編譯期常量和運作期常量

2、讀取或設定一個類型的靜态字段(非編譯期常量)的時候會進行初始化

3、調用一個類型的編譯期常量的時候不會導緻該類初始化,甚至該類都不會被加載

4、對于靜态字段,隻有直接定義了這個字段的類才會被初始化

5、接口中都是靜态常量

接口的特殊點:

1、實作該接口的子類或者子接口進行初始化的時候,不會根據那七種情況中的子類初始化會導緻父類初始化這條規則,導緻父接口的初始化。

2、隻有調用該接口的運作期常量的時候,才會導緻接口的初始化。

注:

1、删除class檔案,不能用來判斷是否進行了初始化,隻能用來判斷是否進行了加載。

2、接口作為父接口跟類作為父類的差別在于:接口是被動的,類是主動的。

對于接口,不管你是否實作我,隻有你引用我的運作期常量,我才會初始化。

對于類,隻要你實作我,則你初始化我就初始化;或者引用我的運作期常量,我就會初始化。

2、準備階段與初始化階段

引例:猜輸出

public class MyTest6 {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        System.out.println("counter1" + Singleton.counter1);
        System.out.println("counter2" + Singleton.counter2);
    }
}

class Singleton {
    public static int counter1;

    public static int counter2 = 0;

    private static Singleton singleton = new Singleton();

    private Singleton() {
        counter1++;
        counter2++;
    }

    public static Singleton getInstance() {
        return singleton;
    }
}
           

我的想法:在main方法裡面調用了Singleton類的靜态方法,是主動使用的一種情形,是以該類會初始化,是以counter1、counter2會有初始值0,,而靜态變量singleton會調用私有的構造方法,是以兩者都會自增,是以結果應該是1、1。

實際結果:

counter1: 1
counter2: 1
           

引例變體:猜輸出

public class MyTest6 {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        System.out.println("counter1: " + Singleton.counter1);
        System.out.println("counter2: " + Singleton.counter2);
    }
}

class Singleton {
    public static int counter1;

    private static Singleton singleton = new Singleton();

    private Singleton() {
        counter1++;
        counter2++;
    }

    public static int counter2 = 0;

    public static Singleton getInstance() {
        return singleton;
    }
}
           

我的想法:

在類加載的準備階段,會給給靜态變量指派,此時counter1、counter2應該是0,singleton應該是null。當main方法中調用靜态方法時,進行初始化。因為singleton的初始化在counter2之前,是以counter1應該是1,counter2應該是0。結果應該是1、0.

實際結果:

counter1: 1
counter2: 0
           

可以驗證下,在私有構造方法中輸出一下:

public class MyTest6 {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        System.out.println("counter1: " + Singleton.counter1);
        System.out.println("counter2: " + Singleton.counter2);
    }
}

class Singleton {
    public static int counter1;

    private static Singleton singleton = new Singleton();

    private Singleton() {
        counter1++;
        counter2++;
        System.out.println(counter1);
        System.out.println(counter2);
    }

    public static int counter2 = 0;

    public static Singleton getInstance() {
        return singleton;
    }
}
           

結果:

1
1
counter1: 1
counter2: 0
           
jvm