类字面常量

楔子

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 的访问中所看到的那样。

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