主题
ReflectionUtil 反射工具
cn.com.digitalhainan.tools.ReflectionUtil
功能简介
ReflectionUtil 提供常用的反射操作功能,包括获取泛型类型、访问私有字段、调用私有方法等,简化反射编程。
核心方法
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
getSuperClassGenericType(Class clazz, int index) | clazz: 类类型 index: 泛型参数索引 | Class | 获取父类泛型参数类型 |
getSuperGenericType(Class clazz) | clazz: 类类型 | Class<T> | 获取父类第一个泛型参数类型 |
getDeclaredMethod(Object object, String methodName, Class<?>[] parameterTypes) | object: 目标对象 methodName: 方法名 parameterTypes: 参数类型 | Method | 获取声明的方法(含父类) |
getDeclaredField(Object object, String filedName) | object: 目标对象 filedName: 字段名 | Field | 获取声明的字段(含父类) |
invokeMethod(...) | ... | Object | 调用方法(忽略访问修饰符) |
setFieldValue(...) | ... | void | 设置字段值(忽略访问修饰符) |
getFieldValue(...) | ... | Object | 获取字段值(忽略访问修饰符) |
makeAccessible(Field field) | field: 字段 | void | 设置字段可访问 |
代码示例
获取父类泛型类型
java
import cn.com.digitalhainan.tools.ReflectionUtil;
// 定义带泛型的父类
public abstract class BaseDao<T, ID> {
private Class<T> entityClass;
private Class<ID> idClass;
@SuppressWarnings("unchecked")
public BaseDao() {
// 获取第一个泛型参数类型
this.entityClass = ReflectionUtil.getSuperGenericType(getClass());
// 获取第二个泛型参数类型
this.idClass = ReflectionUtil.getSuperClassGenericType(getClass(), 1);
}
}
// 子类继承时指定泛型
public class UserDao extends BaseDao<User, Long> {
// entityClass = User.class
// idClass = Long.class
}访问私有字段
java
import cn.com.digitalhainan.tools.ReflectionUtil;
public class UserService {
private String secretKey = "abc123";
}
// 获取私有字段值
UserService service = new UserService();
Object secretKey = ReflectionUtil.getFieldValue(service, "secretKey");
System.out.println(secretKey); // 输出:abc123
// 设置私有字段值
ReflectionUtil.setFieldValue(service, "secretKey", "newKey456");调用私有方法
java
import cn.com.digitalhainan.tools.ReflectionUtil;
public class Calculator {
private int add(int a, int b) {
return a + b;
}
}
// 调用私有方法
Calculator calc = new Calculator();
Object result = ReflectionUtil.invokeMethod(
calc, // 目标对象
"add", // 方法名
new Class[]{int.class, int.class}, // 参数类型
new Object[]{10, 20} // 参数值
);
System.out.println(result); // 输出:30获取字段和方法
java
import cn.com.digitalhainan.tools.ReflectionUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectionDemo {
public void demo() {
User user = new User();
// 获取字段(含父类)
Field field = ReflectionUtil.getDeclaredField(user, "username");
System.out.println("字段类型:" + field.getType());
// 获取方法(含父类)
Method method = ReflectionUtil.getDeclaredMethod(
user,
"setUsername",
new Class[]{String.class}
);
System.out.println("方法名:" + method.getName());
}
}实用场景:对象拷贝
java
import cn.com.digitalhainan.tools.ReflectionUtil;
import java.lang.reflect.Field;
public class BeanUtil {
/**
* 复制对象属性(同名字段)
*/
public static void copyProperties(Object source, Object target) {
Field[] sourceFields = source.getClass().getDeclaredFields();
for (Field sourceField : sourceFields) {
String fieldName = sourceField.getName();
try {
// 获取源对象字段值
Object value = ReflectionUtil.getFieldValue(source, fieldName);
// 设置到目标对象
ReflectionUtil.setFieldValue(target, fieldName, value);
} catch (Exception e) {
// 字段不存在或类型不匹配,跳过
}
}
}
}实用场景:打印对象属性
java
import cn.com.digitalhainan.tools.ReflectionUtil;
import java.lang.reflect.Field;
public class DebugUtil {
/**
* 打印对象所有字段值(用于调试)
*/
public static String toString(Object obj) {
if (obj == null) {
return "null";
}
StringBuilder sb = new StringBuilder(obj.getClass().getSimpleName() + "{");
Field[] fields = obj.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
String fieldName = fields[i].getName();
try {
Object value = ReflectionUtil.getFieldValue(obj, fieldName);
sb.append(fieldName).append("=").append(value);
if (i < fields.length - 1) {
sb.append(", ");
}
} catch (Exception e) {
sb.append(fieldName).append("=ERROR");
}
}
sb.append("}");
return sb.toString();
}
}注意事项
- 异常处理:方法内部已处理部分异常,但
invokeMethod可能抛出InvocationTargetException - 性能考虑:反射操作比直接调用慢,高频场景建议缓存 Method/Field 对象
- 访问控制:
makeAccessible可绕过 Java 访问控制检查,但可能受 SecurityManager 限制 - 泛型擦除:获取的泛型类型是编译时类型,运行时泛型信息可能丢失
- 空值处理:字段不存在时抛出
IllegalArgumentException,注意捕获处理
