Class对象

Class对象的创建时间

Class 对象的创建发生在类加载过程的「链接阶段的结束」到「初始化阶段的开始」之间 (主流 HotSpot 虚拟机实现),且一定是在类初始化之前就已创建完成,而非 "加载完后"(加载阶段仅完成二进制字节码加载,尚未形成完整的 Class 对象)。

HotSpot 虚拟机中,Class对象(也叫 "类元信息对象")的创建是加载阶段启动,但链接阶段完成

  1. 加载阶段 :虚拟机读取字节码后,先在堆内存(注意:方法区存类的运行时数据,Class 对象存堆)创建一个空的 Class 对象雏形,仅记录类的全限定名、父类等基础信息,此时 Class 对象不可用;
  2. 链接阶段(验证 + 准备 + 解析) :虚拟机逐步完善 Class 对象的内容(如静态变量的内存地址、方法的直接引用、接口信息等);
  3. 链接阶段结束后、初始化阶段开始前 :Class 对象完全创建完成,此时可以通过Class.forName()类名.class等方式获取到这个对象,但类的静态变量还未执行用户指定的赋值(初始化阶段才做)。

方法区存类的运行时数据,Class 对象存堆

java 复制代码
public class ClassObjectTiming {
    // 静态变量(初始化阶段执行赋值)
    public static final String TEST = "初始化完成";

    static {
        System.out.println("执行静态代码块(初始化阶段)");
    }

    public static void main(String[] args) throws ClassNotFoundException {
        // 方式1:通过类名.class获取Class对象(仅触发加载+链接,不触发初始化)
        Class<ClassObjectTiming> clazz1 = ClassObjectTiming.class;
        System.out.println("获取Class对象:" + clazz1.getName());
        System.out.println("此时静态变量值:" + clazz1.getField("TEST").get(null)); // 能获取到默认值/常量值,但未执行静态代码块

        // 方式2:Class.forName(类名, false, 类加载器) ------ false表示不触发初始化
        Class<?> clazz2 = Class.forName("ClassObjectTiming", false, ClassObjectTiming.class.getClassLoader());
        System.out.println("再次获取Class对象:" + clazz2.getName());

        // 方式3:Class.forName(类名) ------ 触发初始化
        Class<?> clazz3 = Class.forName("ClassObjectTiming");
        System.out.println("初始化后获取:" + clazz3.getName());
    }
}
output:
获取Class对象:ClassObjectTiming
此时静态变量值:初始化完成
再次获取Class对象:ClassObjectTiming
执行静态代码块(初始化阶段)
初始化后获取:ClassObjectTiming

常见误区澄清

  1. 误区 1:"加载完就创建 Class 对象"

    → 加载阶段仅生成 Class 对象雏形,链接阶段(验证 / 准备 / 解析)才完成 Class 对象的初始化,加载阶段结束后 Class 对象尚未就绪;

  2. 误区 2:"Class 对象在方法区"

    → HotSpot 中,类的运行时数据(如常量池、方法信息)存在方法区(元空间),但Class对象本身存放在堆内存中;

  3. 误区 3:"获取 Class 对象就等于类初始化"

    → 只有触发《Java 虚拟机规范》中规定的 5 种 "主动使用" 场景(如 new 实例、调用静态方法、反射且不指定不初始化),才会触发初始化,单纯获取 Class 对象(如类名.class)仅触发加载 + 链接。

相关推荐
向上的车轮5 小时前
为什么.NET(C#)转 Java 开发时常常在“吐槽”Java:checked exception
java·c#·.net
Dragon Wu5 小时前
Spring Security Oauth2.1 授权码模式实现前后端分离的方案
java·spring boot·后端·spring cloud·springboot·springcloud
跳动的梦想家h5 小时前
环境配置 + AI 提效双管齐下
java·vue.js·spring
坚持就完事了5 小时前
Java中的集合
java·开发语言
wjhx5 小时前
QT中对蓝牙权限的申请,整理一下
java·数据库·qt
YCY^v^5 小时前
JeecgBoot 项目运行指南
java·学习
人间打气筒(Ada)6 小时前
jenkins基于Pipeline发布项目
java·pipeline·jenkins·流水线·ci·cd·cicd
爬山算法6 小时前
Hibernate(88)如何在负载测试中使用Hibernate?
java·后端·hibernate
自不量力的A同学6 小时前
Solon AI v3.9 正式发布:全能 Skill 爆发
java·网络·人工智能
万岳科技系统开发6 小时前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法