類字面常量

楔子

java 8 學習筆記

類字面常量

Java還提供了另一種方法來生成對象的引用:類字面常量,對上述程序來說,就像這樣FancyToy.class。這樣做不僅更簡單,而且更安全,因爲它在編譯時就會受到檢查。並且它根除了對forName方法的調用,所以效率更高。

類字面量不可可以用於普通類,也可以應用於接口、數組以及基本數據類型。另外,對應基本數據類型包裝類,還有一個標準字段TYPE.

當使用.class來創建對Class對象的引用時,不會自動地初始化該Class對象。爲了使用類而做的準備工作實際包含了三個步驟

  1. 加載:這是類加載器執行的。該步驟檢查字節碼(通常在classpath所指定的路徑中查找,但這並非是必須的),並從這些字節碼 中創建一個Class對象。
  2. 鏈接:在鏈接階段將驗證類中的字節碼,爲static字段分配存儲空間,並且如果需要的話,將解析這個類創建的對其他類的所有引用。
  3. 初始化:如果該類具有超類,則先初始化超類,執行static初始化器和static初始化塊。

直到第一次引用一個static方法(構造器隱式地是static)或者非常量的static字段,纔會進行類初始化。

package com.study.java8.char18;

/**
 * @author study
 * @version 1.0
 * @description
 * @date 2020/6/7 20:31
 */
// typeinfo/ClassInitialization.java

import java.util.*;

class Initable {
    static final int STATIC_FINAL = 47;
    static final int STATIC_FINAL2 =
            ClassInitialization.rand.nextInt(1000);

    static {
        System.out.println("Initializing Initable");
    }
}

class Initable2 {
    static int staticNonFinal = 147;

    static {
        System.out.println("Initializing Initable2");
    }
}

class Initable3 {
    static int staticNonFinal = 74;

    static {
        System.out.println("Initializing Initable3");
    }
}

public class ClassInitialization {
    public static Random rand = new Random(47);


    /********************************/
    public static void main(String[] args) throws Exception {
        Class initable = Initable.class;
        System.out.println("After creating Initable ref");
        // Does not trigger initialization:
        System.out.println(Initable.STATIC_FINAL);
        // Does trigger initialization:
        System.out.println(Initable.STATIC_FINAL2);
        // Does trigger initialization:
        System.out.println(Initable2.staticNonFinal);
        Class initable3 = Class.forName("com.study.java8.char18.Initable3");
        System.out.println("After creating Initable3 ref");
        System.out.println(Initable3.staticNonFinal);
    }
}

After creating Initable ref
47
Initializing Initable
258
Initializing Initable2
147
Initializing Initable3
After creating Initable3 ref
74

初始化有效地儘可能的“惰性”,從對initable 引用的創建中可以看到,僅使用.class語法來獲得對類對象的引用不會引發初始化。但與此相反,使用Class.forName() 來產生 Class 引用會立即就進行初始化,如 initable3
如果一個 static final值是編譯期常量 (如 Initable.staticFinal) 那麼這個值不需要對 Initable 類進行初始化就可以被讀取。但是 ,如果只是將一個字段設置爲 staticfinal ,還不足以確保這種行爲,例如,對Initable.staticFinal2 的訪問將強制進行類的初始化,因爲它不是一個編譯期常量。
如果一個static 字段不是 final的,那麼在對它訪問時,總是要求它在被讀取之前,要麼進行鏈接(爲這個字段分配存儲空間) 和初始化(初始化存儲該空間),就像對 Initable2.staticNonFinal 的訪問中所看到的那樣。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章