Java反射入门
反射基础概念
反射(Reflection)是Java语言的一个重要特性,它允许程序在运行时动态地获取类的信息并操作类或对象的属性、方法。
核心特点:
运行时获取类的完整结构信息
动态创建对象实例
动态调用方法和访问属性
绕过访问权限检查(访问私有成员)
反射核心API
1. 获取Class对象的三种方式
1 | // 1. 通过类名.class获取 |
2. 常用反射操作
1 | // 创建实例 |
反射的应用场景
- 框架开发:Spring、Hibernate等框架大量使用反射实现依赖注入、动态代理等功能
- 动态代理:AOP编程的基础
- 注解处理:运行时通过反射读取注解信息
- 单元测试:测试私有方法
- 通用工具:如BeanUtils.copyProperties等属性拷贝工具
反射的性能问题与优化
反射虽然强大,但存在明显的性能问题:
- 动态解析开销:反射操作比直接调用慢很多。每次反射调用都需要解析类、方法、字段的元数据;需要检查方法签名、参数类型等
- JIT优化受限:直接调用可以被JIT内联优化;反射调用是动态的,难以优化
- 安全检查:每次调用都要检查访问权限;需要验证参数类型等
优化建议:
缓存反射对象:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// 不好的做法:每次调用都获取Method
public void slowReflection(Object obj, String methodName) throws Exception {
Method method = obj.getClass().getMethod(methodName);
method.invoke(obj);
}
// 好的做法:缓存Method
private static Map<String, Method> methodCache = new HashMap<>();
public void fastReflection(Object obj, String methodName) throws Exception {
Method method = methodCache.get(methodName);
if (method == null) {
method = obj.getClass().getMethod(methodName);
methodCache.put(methodName, method);
}
method.invoke(obj);
}**跳过安全检查setAccessible(true)**:
1
2
3Field field = clazz.getDeclaredField("privateField");
field.setAccessible(true); // 只需设置一次
// 后续访问不再检查访问权限
反射的安全问题
反射可以突破Java的访问控制机制,带来安全隐患:
- 访问私有成员:可能导致敏感信息泄露
- 修改final字段:破坏不可变性设计
- 调用任意方法:可能执行危险操作
反射的应用示例
Spring IOC容器简化实现
1 | /** |