实例解析Java反射
字数 747 2025-08-12 11:34:33
Java反射机制详解
一、反射概述
反射(Reflection)是Java语言的重要特性,它允许程序在运行时动态获取类的信息并操作类或对象的属性和方法。反射机制打破了Java的静态特性,为Java赋予了动态能力。
核心特性:
- 运行时获取任意类的完整结构(类名、方法、属性、构造器等)
- 运行时创建对象
- 运行时调用方法和访问属性
- 操作内部类和私有成员
二、反射核心API
1. 获取Class对象
// 方式1:Class.forName()
Class<?> clazz = Class.forName("完整类名");
// 方式2:类名.class
Class<?> clazz = Person.class;
// 方式3:对象.getClass()
Person p = new Person();
Class<?> clazz = p.getClass();
// 方式4:ClassLoader加载
this.getClass().getClassLoader().loadClass("完整类名");
2. 实例化对象
// 无参构造
Object obj = clazz.newInstance();
// 带参构造
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
Object obj = constructor.newInstance("参数1", 参数2);
3. 操作方法
// 获取方法
Method method = clazz.getMethod("方法名", 参数类型.class, ...);
// 调用方法
method.invoke(实例对象, 参数值1, 参数值2, ...);
// 获取私有方法
Method privateMethod = clazz.getDeclaredMethod("私有方法名", 参数类型.class);
privateMethod.setAccessible(true); // 突破访问限制
4. 操作属性
// 获取公共属性
Field field = clazz.getField("属性名");
// 获取私有属性
Field privateField = clazz.getDeclaredField("私有属性名");
privateField.setAccessible(true); // 突破访问限制
// 设置属性值
field.set(实例对象, 值);
// 获取属性值
Object value = field.get(实例对象);
三、反射应用实例
1. 基本反射操作
public class Person {
private String name;
public int age;
public void act() {
System.out.println("test");
}
// 构造方法、getter/setter省略...
}
// 反射操作示例
Class<?> c = Class.forName("Person");
// 实例化对象
Constructor<?> constructor = c.getConstructor(String.class, int.class);
Person p1 = (Person) constructor.newInstance("abc", 22);
// 操作属性
Field ageField = c.getField("age");
ageField.set(p1, 11);
Field nameField = c.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(p1, "xinyuan");
// 调用方法
Method actMethod = c.getMethod("act");
actMethod.invoke(p1);
2. 在反序列化中的应用
反射常用于反序列化漏洞利用中,可以实现:
- 定制需要的对象
- 通过invoke调用非同名函数
- 通过Class类创建对象
- 引入不能序列化的类
3. URLDNS链示例(反射应用)
public static void main(String[] args) throws Exception {
HashMap<URL, Integer> hashMap = new HashMap<>();
URL u = new URL("http://dnslog地址");
// 反射修改hashCode值
Class<?> c = u.getClass();
Field hashcodeField = c.getDeclaredField("hashCode");
hashcodeField.setAccessible(true);
hashcodeField.set(u, 123); // 临时修改为非-1的值
hashMap.put(u, 123);
// 恢复hashCode为-1
hashcodeField.set(u, -1);
// 序列化操作...
}
原理分析:
- URL类重写了hashCode方法,调用时会发起DNS请求
- HashMap在反序列化时会调用key的hashCode方法
- 通过反射临时修改hashCode值避免提前触发DNS请求
四、反射的优缺点
优点:
- 提高代码灵活性
- 实现动态创建对象和调用方法
- 突破访问限制,操作私有成员
- 为框架开发提供基础支持
缺点:
- 性能开销较大
- 破坏封装性
- 增加代码复杂度
- 可能引发安全问题
五、安全注意事项
反射机制强大但危险,使用时需注意:
- 避免暴露反射接口给不可信输入
- 谨慎操作私有方法和属性
- 注意反射调用可能引发的安全问题
- 在反序列化中,反射常被用于漏洞利用
六、总结
Java反射机制是Java语言强大的动态特性,通过Class、Constructor、Method、Field等核心类,可以在运行时获取和操作类的各种元素。合理使用反射可以大大提高程序的灵活性,但同时也需要注意其带来的性能和安全问题。