类型信息

本文介绍了Java中的类加载过程及初始化机制,包括RTTI和反射机制的作用,类加载器系统的组成,以及类如何在JVM中动态加载。此外,文章还详细解释了使用Class对象的不同方法来触发类的初始化,并通过示例展示了初始化的具体行为。
摘要由CSDN通过智能技术生成

1、java主要有两种方式在运行时识别对象和类的信息:RTTI和“反射”机制。
2、类加载器系统实际上可以包含一条类加载器链,但是只有一个原生态加载器,它是JVM实现的一部分。原生态加载器加载的是所谓的可信类,包括Java API,它们通常都是从本地盘加载的。在这条链中,通常不需要添加额外的类加载器,但是如果你有需求,那么你有一种方式可以挂载额外的类加载器。
3、所有的类都是在对其第一次使用时,动态加载到JVM中。java程序再它开始运行之前并非完全加载,其各个部分是在必需时才加载。
4、使用Class.forName()加载类时,必需使用全限定名(包括包名)。
5、java还提供了“类字面常量”来获得Class对象的引用。即类A获取Class引用的方法为A.class。这样做不仅简单,安全(因为在编译期是就会检查),而且比forName的方法高效。对于基本类型的包装类,还有一个标准字段TYPE指向Class对象的引用。boolean.class等价于Boolean.TYPE。
6、 为了使用类而做的准备有三个步骤:

加载:由类加载器进行,该步骤将查找字节码,并从字节码中创建Class对象引用。
链接:验证类中的字节码,为静态域分配存储空间,并且如果必须的话,将解析这个类创建的对其他类的所有引用。
初始化:如果该类具有超类,则对其初始化,执行静态初始化器和静态初始化块。
public class Initable {
    static final int staticFinal = 47;
    static final int staticFinal2 = new Random().nextInt(100);
    static {
        System.out.println("Initable");
    }
}

public class Initable2 {
    static int staticNonFinal = 74;
    static{
        System.out.println("Initable2");
    }
}
public class Initable3 {
    static int staticNonFinal = 174;
    static{
        System.out.println("Initable3");
    }
}
public class ClassInitialization {
    public static void main(String[] args) throws Exception{
        Class initable = Initable.class; //不会引起初始化

        System.out.println("after creating Initable reference");
        System.out.println(Initable.staticFinal); //引用编译器常量不会引起初始化

        System.out.println(Initable.staticFinal2); //引起初始化

        System.out.println(Initable2.staticNoFinal); //引用非编译期常量会引起初始化

        Class initable3 = Class.forName("Initable3"); //默认会引起初始化

        System.out.println("after creating Initable3 reference");
        System.out.println(Initable3.staticNoFinal);//前面已经初始化此处不用再初始化

    }
}

/* Output
After creating Initable ref
47
Initable
15
Initable2
74
Initable3
After creating Initable3 ref
174
*/

初始化有效地实现了尽可能的“惰性”。仅使用.class不会触发类的初始化。而调用Class.forName会导致类初始化。(比如Initable.class和Class.forName("com.yanguang.Initable3"))
如果一个类的变量是static final的
    这个变量的值是编译器常量:这个值可以在类不被初始化时就可以读取。(Initable.staticFinal)
    这个变量的值动态获得(比如通过随机函数生成),那么对这个值得调用会导致类的初始化。(Initable.staticFinal2)
如果一个static域不是final的,那么在访问它时,总是要求在它被读取前,先进行链接(分配空间)和初始化(初始化该空间)。(Initable2.staticNonFinal)

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值