1. 什么是反射
反射(Reflection)是 Java 提供的一种在运行时动态获取类的信息,并能操作类的属性和方法的机制 。
通过反射,你可以在不知道对象具体类型的情况下,操作它的属性、方法、构造函数等。
使用idea时的自动提示就是依赖了反射机制。
反射的核心是**java.lang.reflect
** 包。
字节码文件的本质
class
文件是 跨平台的中间表示形式,里面存放着:
类的元信息(类名、父类、接口等)
成员变量信息
方法的字节码指令
常量池(字符串常量、方法引用等)
我们可以通过反射获取这些信息。
所以 Java 实现了"一次编译,到处运行":
- Windows、Linux、Mac 各自有 JVM,能识别同样的
.class
文件并执行。
2. 反射的主要功能
获取类的字节码信息
java
Class<?> clazz = Class.forName("java.util.ArrayList");
三种获取方式:
Class.forName("全限定类名")
类名.class
对象.getClass()
-
获取类的信息
-
类名:
clazz.getName()
、clazz.getSimpleName()
-
包名:
clazz.getPackage()
-
-
获取构造方法
javaConstructor<?>[] constructors = clazz.getConstructors(); // 公共构造方法 Constructor<?> constructor = clazz.getDeclaredConstructor(String.class); // 指定构造器
javagetConstructors() 获取 所有 public 构造方法。 getDeclaredConstructors() 获取 所有构造方法(包括 private、protected、default、public)。 getConstructor(Class<?>... parameterTypes) 获取 指定参数类型的 public 构造方法。 getDeclaredConstructor(Class<?>... parameterTypes) 获取 指定参数类型的构造方法(不管访问修饰符)。
-
获取字段(成员变量)
javaField[] fields = clazz.getDeclaredFields(); // 所有字段 Field field = clazz.getDeclaredField("name"); field.setAccessible(true); // 允许访问 private field.set(obj, "Tom"); // 给字段赋值
-
获取方法
javaMethod[] methods = clazz.getDeclaredMethods(); Method method = clazz.getDeclaredMethod("setName", String.class); method.invoke(obj, "Tom"); // 调用方法
-
操作对象
Object obj = clazz.getDeclaredConstructor().newInstance(); // 创建对象
总结:
-
public 构造方法 :用
getConstructors()
或getConstructor(...)
。 -
所有构造方法(包括 private) :用
getDeclaredConstructors()
或getDeclaredConstructor(...)
,并且要setAccessible(true)
才能使用。(暴力反射,不管是不是private)
-
获取成员变量:
-
getField
→ public 字段(含继承) -
getDeclaredField
→ 本类所有字段(private/protected/public/默认)
-
-
操作 private 字段:
setAccessible(true)
-
获取/修改值:
get(obj)
/set(obj, value)
-
反射可以获取字段名、类型、注解信息等,非常灵活,但性能比直接访问慢一些。
反射的应用场景
应用方向 | 案例 | 技术体现 |
---|
|-------|-----------|-------------------------------------|
| 动态类加载 | 插件系统、工厂模式 | Class.forName()
+ newInstance()
|
|--------|-------------|-------------------|
| 动态方法调用 | MVC 框架、测试工具 | Method.invoke()
|
|--------|-----------------|---------------------|
| 动态字段访问 | ORM 框架、JSON 序列化 | Field.get()/set()
|
|------|--------------|-----------------------------------|
| 注解解析 | Spring、JUnit | isAnnotationPresent()
, 反射扫描类/方法 |
|------|---------|----------------------------|
| 动态代理 | AOP、RPC | Proxy.newProxyInstance()
|
|------|------------|----------------|
| 配置驱动 | 任务调度、自动化脚本 | 结合反射解析配置执行类/方法 |
✅ 核心结论 :
反射的最大价值是 通用性和灵活性 ,它允许程序在运行时动态处理类、对象和方法,解耦、框架化、插件化、自动化。