Java反射(一)——Class对象

本文介绍了Java反射机制中的核心概念Class对象,阐述了Class对象在反射中的重要性,以及Class类的特性,包括其不可被继承、作为泛型类以及实现的接口。接着,详细讲解了如何生成Class对象,涉及类加载过程的加载、链接和初始化三个步骤,并列举了触发类加载的常见场景。最后,提到了Class对象在内存中的唯一性以及类加载器的角色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 Class对象

Java的反射机制离不开一个被称为Class对象的特殊对象,它包含了与类有关的信息。
为什么说离不开Class对象呢?
因为Java反射机制就是:

运行状态中,对任意一个实体类,都能够知道这个类的所有属性和方法;对任意一个对象,都能够调用它的任一方法和属性。

所以我们就先来弄清楚Class对象是个怎样“特殊”的对象,再去理解反射就容易多了。

2 Class类

类与对象(类实例)的关系:

对象是类的实例,类是对象的模板。

既然是Class对象,自然就又一个叫做Class类的实体类(虽然名字有点奇怪),我们可以在Java.lang包的Class.class文件中找到Class类的源码,有兴趣的同学,可以自己打开看看,这里贴上部分源码:

public final class Class<T> implements java.io.Serializable,
                              GenericDeclaration,
                              Type,
                              AnnotatedElement {
    private static final int ANNOTATION= 0x00002000;
    private static final int ENUM      = 0x00004000;
    private static final int SYNTHETIC = 0x00001000;

    private static native void registerNatives();
    static {
        registerNatives();
    }

    /*
     * Private constructor. Only the Java Virtual Machine creates Class objects.
     * This constructor is not used and prevents the default constructor being
     * generated.
     */
    private Class(ClassLoader loader) {
        // Initialize final field for classLoader.  The initialization value of non-null
        // prevents future JIT optimizations from assuming this final field is null.
        classLoader = loader;
    }

    ......

我们顺带的来简单的分析一下Class实体类:

  • final修饰的类:Class类不可被继承的;
  • Class:Class类是泛型类;
  • 实现了四个接口;
  • 没有公共的构造方法,源码注释说私有方法只有JVM能够调用并创建对象。

源码后面还有很多的方法,我们后面可以看到作用以及如何使用。

了解Class类了,我们下一步就是去探究Class对象如何创建了,我们需要的是Class对象!

3 生成Class对象

Class对象包含了与类有关的信息,类是程序的一部分,每个类都有一个Class对象,换言之,每当编写并且编译了一个新类,就会产生一个Class对象(更恰当的地说,是被保存在一个同名的.class文件中)。为了生成这个类的对象,运行这个程序的JVM将使用被称为“类加载器”的子系统。

所有的类都是在对其第一次使用时,动态加载到JVM中的。下图描述的就是从类第一次使用,到生成Class对象的过程:

Class对象生成过程

【1】程序运行时,类第一次使用,触发JVM进行类加载

常见的触发场景:

  • 使用new关键字实例化对象
  • 读取或设置一个类的静态字段(编译期常量除外)
  • 调用一个类的静态方法

【2】通过一个类的全限定名来获取定义此类的二进制字节流

假设程序运行在本地,那么就是通过包名.类名到本地磁盘查找对应的.class文件,并将其加载到JVM中。

除了在本地.class格式文件获取以外,Class文件还有可能是从ZIP包、网络、数据库等其他形式的载体中读取的。当然这通常需要我们自定义类加载器,即重写类加载器的loadClass()方法。

【3】在内存中生成一个代表这个类的java.lang.Class对象

一旦Class对象被载入内存之后,它就被用来创建这个类的所有对象。

一个类在内存中有且仅有一个与之对应的Class对象,与该类产生的实例个数无关。


我们这里只是讲到Class对象的生成,并非是类加载的全过程,所以暂时不再展开后面的部分。

类加载的过程有三个步骤:

  1. 加载,这是由类加载器执行的。查找字节码,并从这些字节码中创建一个Class对象。

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

  3. 初始化。如果该类具有超类,则对其初始化,执行静态初始化器和静态初始化块。

Class对象的生成是在类的加载阶段。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值