类字面常量 .class -- 《JAVA编程思想》46

假如我们想获取一个 Class 对象的引用,不仅可以通过 Class.forName (String className) 来获取,还可以通过类字面常量来获取对 Class 对象的引用。

		// 第一种方式:Class.forName(String className)
        try {
    
    
            Class.forName("mtn.baymax.charpter14.Gum");
        } catch (ClassNotFoundException e) {
    
    
            System.out.println("未找到 Gum 类");
        }
		// 第二种方式:类字面常量
    	Class gum = Gum.class;

通过 Class.forName(String className) 加载的 Class 对象是及时加载的,这种加载方式可能会抛出异常,因为指定的类可能存在路径不正确或者无访问权限等情况,但通过类字面常量来加载的话,在编译时就会受到检查,也更为高效,推荐使用“.class”的形式来获取 Class 对象。

类字面常量不仅可以作用于普通的类,还可以作用于接口、数组以及基本数据类型。每个基本数据类型的包装器类都拥有一个标准字段 TYPE,也能通过它获取基本数据类型的 Class 对象。

            Class a= Boolean.TYPE;
            Class b = Boolean.class;
包装器类 TYPE类型
boolean.class Boolean.TYPE
char.class Char.TYPE
byte.class Byte.TYPE
short.class Short.TYPE
int.class Integer.TYPE
long.class Long.TYPE
float.class Float.TYPE
dobule.class Double.TYPE
void.class Void.TYPE
boolean.class Boolean.TYPE

接下来,一起来了解 “.class” 来创建对 Class 对象的引用时,执行的三个步骤:

1.加载
类加载器查找字节码,并根据字节码创建一个 Class 对象。

2.链接
验证类中的字节码,为静态域分配存储空间,解析这个类创建时对其他类的所有引用。

3.初始化
如果该类有超类,则对超类进行初始化,再执行静态初始化器(按顺序依次生成类中的每个成员)和静态初始化块( static{ } )。

只有对静态方法(构造器是隐式的静态方法)或者非静态域首次引用时,才会对类执行初始化操作,故类字面常量的加载方式为惰性加载

通过一个例子来验证结论:

public class Initable {
    
    

    static final int staticFinal = 47;

    static final int staticFinal2 = new Random().nextInt(27);

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

}

public class Initable2 {
    
    

    static int staticNonFinal = 147;

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

public class Initable3 {
    
    

    static int staticNonFinal = 74;

    static {
    
    
        System.out.println("Init Initable3");
    }
    
}
public class ClassInitialization {
    
    

    public static void main(String[] args) throws ClassNotFoundException {
    
    
        Class initable = Initable.class;
        System.out.println("准备初始化 initable ");
        System.out.println(Initable.staticFinal);
        System.out.println(Initable.staticFinal2);
        System.out.println("准备初始化 initable2 ");
        System.out.println(Initable2.staticNonFinal);
        Class initable3 = Class.forName("mtn.baymax.charpter14.Initable3");
        System.out.println("准备初始化 initable3 ");
        System.out.println(Initable3.staticNonFinal);
    }

}
准备初始化 initable 
47
Init Initable
10
准备初始化 initable2 
Init Initable2
147
Init Initable3
准备初始化 initable3 
74

Initable.staticFinal 是一个 static final 类型的值,为编译期常量,故不需要对类进行初始化就可进取读取。 Initable.staticFinal2 虽然也是 static final 类型,但其只有在运行期间才能知道具体的值,故获取它时需要对类进行初始化。

staticFinal2 = new Random().nextInt(27);

Initable2.staticNonFinal 为静态变量,对其进行访问需要对类进行初始化。

Class initable3 采用的是 Class.forName(String className ) 及时加载的方式,故在对静态变量访问之前,类的初始化就已经完成。

本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。

若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!

猜你喜欢

转载自blog.csdn.net/BaymaxCS/article/details/119343497
今日推荐