Java反射获取Class对象有三种方式:类名.class最安全高效,适用于编译期已知类型;Class.forName()支持动态加载并触发初始化,适合配置驱动场景;obj.getClass()用于运行时实例外观推导,依赖对象存在。

Java 反射机制获取类与对象信息,核心是先拿到 Class 对象,再通过它读取类结构、字段、方法、构造器等元数据。整个过程不依赖源码,而是基于运行时加载的 .class 字节码文件。
怎么获取 Class 对象
有三种常用方式,适用场景不同:
-
类名.class:编译期已知类型,最安全高效。不会触发类初始化,适合工具类、泛型参数传递等场景。例如:
User.class -
对象.getClass():已有实例时使用,返回该实例实际运行时的 Class 类型(支持多态)。注意返回类型是
Class<?>,需谨慎强转。 -
Class.forName("全限定类名"):运行时动态加载类,会立即触发类的静态初始化块和静态字段赋值。适用于配置驱动、插件化场景,比如
Class.forName("com.example.User")
怎么获取类的结构信息
拿到 Class 对象后,就能系统性地“解剖”这个类:
- 获取类名:
clazz.getName()(含包名)、clazz.getSimpleName()(仅类名) - 获取父类:
clazz.getSuperclass();获取实现的接口:clazz.getInterfaces() - 获取所有公共字段:
clazz.getFields();获取全部字段(含私有):clazz.getDeclaredFields() - 获取构造器:
clazz.getConstructors()(仅 public),或clazz.getDeclaredConstructors()(全部) - 获取方法:
clazz.getMethods()(本类 + 继承的 public 方法),clazz.getDeclaredMethods()(仅本类声明的方法,含私有)
怎么操作字段、方法和构造器
反射不只是“看”,还能“动”:
立即学习“Java免费学习笔记(深入)”;
- 对字段:用
Field.setAccessible(true)绕过访问控制,再调用field.set(obj, value)或field.get(obj) - 对方法:获取
Method后,用method.invoke(obj, args...)执行;若为 static 方法,第一个参数传null - 对构造器:用
constructor.newInstance(args...)创建新实例,支持 private 构造器(需先setAccessible(true))
注意事项和限制
反射虽灵活,但有明确边界和代价:
- 无法绕过 final 字段的语义约束(即使 setAccessible,修改 final 基本类型字段可能无效或抛出异常)
- 泛型信息在运行时被擦除,
getGenericXxx()系列方法可部分还原,但不能完全恢复类型实参 - 性能开销明显高于直接调用,频繁使用需权衡;JDK 9+ 模块系统还引入了更强的封装限制(如默认禁止反射访问非开放模块的内部类)
- 安全策略(SecurityManager)或模块导出限制可能导致
IllegalAccessException或InaccessibleObjectException


















