什么是反射?

反射(Reflection) 是Java的一种强大特性,允许程序在运行时动态地获取类的信息(方法、字段、构造器等),并能动态调用对象的方法、访问字段。

通俗理解:把Java类当作"对象"来操作。


核心类

作用
Class 代表一个类或接口
Constructor 代表构造方法
Method 代表成员方法
Field 代表成员变量

获取Class对象的三种方式

java

// 方式1:通过类名.class
Class<?> clazz1 = String.class;

// 方式2:通过对象的getClass()
String s = "hello";
Class<?> clazz2 = s.getClass();

// 方式3:通过Class.forName()(最常用)
Class<?> clazz3 = Class.forName("java.lang.String");

反射能做什么?

1. 获取类的信息

java

Class<?> clazz = Class.forName("java.util.ArrayList");

// 获取类名
System.out.println("类名:" + clazz.getName());

// 获取所有public方法
Method[] methods = clazz.getMethods();
for (Method m : methods) {
    System.out.println(m.getName());
}

// 获取所有字段
Field[] fields = clazz.getDeclaredFields();
for (Field f : fields) {
    System.out.println(f.getName() + " : " + f.getType());
}

2. 动态创建对象

java

// 调用无参构造器
Class<?> clazz = Class.forName("java.util.ArrayList");
Object obj = clazz.newInstance();  // 已废弃,推荐下面的方式

// 推荐方式
Constructor<?> constructor = clazz.getConstructor();
Object obj2 = constructor.newInstance();

3. 动态调用方法

java

Class<?> clazz = Class.forName("java.lang.String");
Object str = clazz.getConstructor(String.class).newInstance("Hello");

// 调用length()方法
Method method = clazz.getMethod("length");
int length = (int) method.invoke(str);
System.out.println(length);  // 输出 5

// 调用substring(int, int)
Method subMethod = clazz.getMethod("substring", int.class, int.class);
String result = (String) subMethod.invoke(str, 1, 4);
System.out.println(result);  // 输出 "ell"

4. 访问/修改私有字段

java

class User {
    private String name = "默认";
}

User user = new User();
Class<?> clazz = user.getClass();
Field field = clazz.getDeclaredField("name");

// 突破private限制(暴力反射)
field.setAccessible(true);

// 读取
String name = (String) field.get(user);
System.out.println(name);  // 默认

// 修改
field.set(user, "反射修改");
System.out.println(field.get(user));  // 反射修改

常见应用场景

场景 说明
框架(Spring、MyBatis) 动态创建Bean、注入依赖
注解处理器 运行时读取注解并执行逻辑
动态代理 JDK动态代理基于反射
IDE自动提示 运行时获取类结构信息
单元测试(JUnit) 动态执行测试方法

性能与注意事项

  • ⚠️ 反射有性能开销(比直接调用慢),不宜在热点代码中频繁使用

  • ⚠️ setAccessible(true) 破坏了封装性,需谨慎使用

  • ✅ 反射是框架底层的基础,理解它有助于深入理解Java生态


完整示例代码

java

public class ReflectionDemo {
    public static void main(String[] args) throws Exception {
        // 1. 获取Class
        Class<?> clazz = Class.forName("java.lang.String");
        
        // 2. 获取构造器创建对象
        Constructor<?> constructor = clazz.getConstructor(String.class);
        Object str = constructor.newInstance("Reflection");
        
        // 3. 调用方法
        Method method = clazz.getMethod("toUpperCase");
        Object result = method.invoke(str);
        System.out.println(result);  // REFLECTION
        
        // 4. 获取所有方法名
        System.out.println("\n=== String所有方法 ===");
        for (Method m : clazz.getDeclaredMethods()) {
            System.out.println(m.getName());
        }
    }
}

小结

核心要点 一句话总结
反射是什么 运行时动态操作类和对象
关键类 Class、Constructor、Method、Field
核心操作 创建对象、调用方法、访问字段
主要用途 框架底层、注解处理、动态代理
注意事项 有性能开销,慎用暴力反射

更多推荐