在 Java 开发领域,反射机制犹如一把神奇的钥匙,能够解锁许多隐藏在代码深处的功能,为开发者提供极大的灵活性与强大的动态编程能力。今天,我们将聚焦于一款精心打造的 ReflectUtil
反射工具类,深入剖析其内部精妙之处,助力大家在 Java 编程的进阶之路上大步前行。
一、工具类概览与基石搭建
ReflectUtil
类位于 com.fink.smallscale.core.utils
包下,引入了强大的日志记录工具 org.apache.logging.log4j
,通过静态常量 logger
精准记录工具类运行中的各类关键信息,无论是调试阶段的细节追踪,还是运行时异常排查,都能让开发者一目了然。这一坚实的日志基础,为整个工具类的稳定运行与问题诊断保驾护航。
二、核心方法深度洞察
(一)属性访问器的反射调用
invokeGetter(T target, String fieldName)
方法:
public static <T> Object invokeGetter(T target, String fieldName)
throws NoSuchMethodException, SecurityException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
// 如果属性名为xxx,则方法名为getXxx
String methodName = "get" + StringUtils.firstCharUpperCase(fieldName);
Method method = target.getClass().getMethod(methodName);
return method.invoke(target);
}
此方法专为调用对象属性的 getter
方法而生。当给定一个目标对象 target
与属性名 fieldName
,它巧妙地按照 JavaBean 的命名规范,动态拼接出对应的 get
方法名(如属性 name
对应 getName
),再利用 getMethod
从类的方法列表中精准获取该方法,最后通过 invoke
触发执行,返回属性值。在实际场景中,若需动态获取对象的某个私有属性值用于业务逻辑判断,此方法便能轻松穿越访问限制,大放异彩。
invokeSetter(T target, String fieldName, Object args)
方法:
public static <T> void invokeSetter(T target, String fieldName, Object args)
throws NoSuchFieldException, SecurityException,
NoSuchMethodException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
// 如果属性名为xxx,则方法名为setXxx
String methodName = "set" + StringUtils.firstCharUpperCase(fieldName);
Class<?> clazz = target.getClass();
Field field = clazz.getDeclaredField(fieldName);
Method method = clazz.getMethod(methodName, field.getType());
method.invoke(target, args);
}
与 invokeGetter
相辅相成,该方法用于调用 setter
方法。首先依据属性名推导出 set
方法名,接着获取目标类的字节码信息,定位到对应的属性字段与方法,确保参数类型匹配无误后,借助 invoke
将传入的参数 args
设置到目标对象的指定属性上。想象一下,在数据批量填充场景下,需要动态为对象的多个属性赋值,它便能高效地完成使命,避免繁琐的手工赋值。
(二)成员信息检索利器
getAllFields(Class<?> clazz)
方法:
public static List<Field> getAllFields(Class<?> clazz) throws Exception {
List<Field> fieldList = new ArrayList<>();
Class<?> tempClass = clazz;
while (tempClass!= null) {
//当父类为null的时候说明到达了最上层的父类(Object类).
fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));
//得到父类,然后赋给自己
tem