Skip to content

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();
    }
}

注意事项

  1. 异常处理:方法内部已处理部分异常,但 invokeMethod 可能抛出 InvocationTargetException
  2. 性能考虑:反射操作比直接调用慢,高频场景建议缓存 Method/Field 对象
  3. 访问控制makeAccessible 可绕过 Java 访问控制检查,但可能受 SecurityManager 限制
  4. 泛型擦除:获取的泛型类型是编译时类型,运行时泛型信息可能丢失
  5. 空值处理:字段不存在时抛出 IllegalArgumentException,注意捕获处理

Power By 数字海南