package com.tudicloud.framework.common.core.util.core;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 反射工具类,提供对类、方法、字段等反射操作的封装。
*
* @Author 孙达
* @Date 2025/11/14 14:10
* @Wechat sundaain
* @Email 18211102099@163.com
* @Copyright <a href="https://www.sundablog.com">孙达博客</a>
*/
public class ReflectionUtils {
// ---------------------- Info ----------------------
/**
* 获取指定类所在的包名。
*
* @param clazz 类对象
* @return 包名字符串
*/
public static String getPackageName(Class<?> clazz) {
return getPackageName(clazz.getName());
}
/**
* 根据完整的类全限定名获取其所在包名。
*
* @param classFullName 完整类名
* @return 包名字符串
*/
public static String getPackageName(String classFullName) {
int lastDot = classFullName.lastIndexOf('.');
return (lastDot < 0) ? "" : classFullName.substring(0, lastDot);
}
// ---------------------- Method ----------------------
/**
* 在给定类及其父类中查找指定名称和参数类型的方法。
*
* @param clazz 要搜索的类
* @param name 方法名称
* @param paramTypes 参数类型数组
* @return 找到的方法对象;如果未找到则返回null
*/
public static Method findMethod(Class<?> clazz, String name, Class<?>... paramTypes) {
AssertUtils.notNull(clazz, "Class must not be null");
AssertUtils.notNull(name, "Method name must not be null");
Class<?> searchType = clazz;
while (searchType != null) {
Method[] methods = (searchType.isInterface()
? searchType.getMethods() :
getDeclaredMethods(searchType, false));
for (Method method : methods) {
if (name.equals(method.getName()) && (paramTypes == null || hasSameParams(method, paramTypes))) {
return method;
}
}
searchType = searchType.getSuperclass();
}
return null;
}
/**
* 判断两个方法是否具有相同的参数列表。
*
* @param method 待比较的方法
* @param paramTypes 目标参数类型数组
* @return 如果参数数量与类型一致返回true,否则false
*/
private static boolean hasSameParams(Method method, Class<?>[] paramTypes) {
return (paramTypes.length == method.getParameterCount() &&
Arrays.equals(paramTypes, method.getParameterTypes()));
}
/**
* 获取类声明的所有方法(包括接口中的默认方法)。
*
* @param clazz 要获取方法的类
* @param defensive 是否防御性复制结果数组
* @return 声明的方法数组
*/
private static Method[] getDeclaredMethods(Class<?> clazz, boolean defensive) {
AssertUtils.notNull(clazz, "Class must not be null");
Method[] result;
try {
Method[] declaredMethods = clazz.getDeclaredMethods();
List<Method> defaultMethods = findConcreteMethodsOnInterfaces(clazz);
if (defaultMethods != null) {
result = new Method[declaredMethods.length + defaultMethods.size()];
System.arraycopy(declaredMethods, 0, result, 0, declaredMethods.length);
int index = declaredMethods.length;
for (Method defaultMethod : defaultMethods) {
result[index] = defaultMethod;
index++;
}
}
else {
result = declaredMethods;
}
} catch (Throwable ex) {
throw new IllegalStateException("Failed to introspect Class [" + clazz.getName() +
"] from ClassLoader [" + clazz.getClassLoader() + "]", ex);
}
return (result.length == 0 || !defensive) ? result : result.clone();
}
/**
* 查找接口中定义的具体实现方法(即非抽象方法,默认方法等)。
*
* @param clazz 当前处理的类
* @return 接口中具体方法列表,如果没有则返回null
*/
private static List<Method> findConcreteMethodsOnInterfaces(Class<?> clazz) {
List<Method> result = null;
for (Class<?> ifc : clazz.getInterfaces()) {
for (Method ifcMethod : ifc.getMethods()) {
if (!Modifier.isAbstract(ifcMethod.getModifiers())) {
if (result == null) {
result = new ArrayList<>();
}
result.add(ifcMethod);
}
}
}
return result;
}
/**
* 设置方法可访问(绕过Java语言访问检查)。
*
* @param method 需要设置为可访问的方法
*/
public static void makeAccessible(Method method) {
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
&& !method.isAccessible()) {
method.setAccessible(true);
}
}
/**
* 调用目标对象上的某个方法,并传入参数。
*
* @param method 方法对象
* @param target 目标实例对象
* @param args 方法调用时传递的参数
* @return 方法执行后的返回值
*/
public static Object invokeMethod(Method method, Object target, Object... args) {
try {
if (args != null) {
return method.invoke(target, args);
} else {
return method.invoke(target);
}
} catch (Exception ex) {
throw new RuntimeException("Failed to invoke method [" + method + "]", ex);
}
}
// ---------------------- Field ----------------------
/**
* 根据字段名在类及其超类中查找对应的字段。
*
* @param clazz 类对象
* @param name 字段名称
* @return 找到的字段对象;若未找到返回null
*/
public static Field findField(Class<?> clazz, String name) {
return findField(clazz, name, null);
}
/**
* 根据字段名及字段类型,在类及其超类中查找对应字段。
*
* @param clazz 类对象
* @param name 字段名称
* @param type 字段类型
* @return 找到的字段对象;若未找到返回null
*/
public static Field findField(Class<?> clazz, String name, Class<?> type) {
AssertUtils.notNull(clazz, "Class must not be null");
AssertUtils.isTrue(name != null || type != null, "Either name or type of the field must be specified");
Class<?> searchType = clazz;
while (Object.class != searchType && searchType != null) {
Field[] fields = getDeclaredFields(searchType);
for (Field field : fields) {
if ((name == null || name.equals(field.getName())) &&
(type == null || type.equals(field.getType()))) {
return field;
}
}
searchType = searchType.getSuperclass();
}
return null;
}
/**
* 获取类声明的所有字段。
*
* @param clazz 类对象
* @return 字段数组
*/
private static Field[] getDeclaredFields(Class<?> clazz) {
AssertUtils.notNull(clazz, "Class must not be null");
Field[] result;
try {
result = clazz.getDeclaredFields();
} catch (Throwable ex) {
throw new IllegalStateException("Failed to introspect Class [" + clazz.getName() + "] from ClassLoader [" + clazz.getClassLoader() + "]", ex);
}
return result;
}
/**
* 设置字段可访问(绕过Java语言访问检查)。
*
* @param field 字段对象
*/
public static void makeAccessible(Field field) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
}
/**
* 给指定字段赋值。
*
* @param field 字段对象
* @param target 目标对象
* @param value 新值
*/
public static void setField(Field field, Object target, Object value) {
try {
field.set(target, value);
} catch (IllegalAccessException ex) {
throw new RuntimeException("Failed to set value to field [" + field + "]", ex);
}
}
/**
* 获取指定字段的当前值。
*
* @param field 字段对象
* @param target 目标对象
* @return 字段当前值
*/
public static Object getField(Field field, Object target) {
try {
return field.get(target);
} catch (IllegalAccessException ex) {
throw new RuntimeException("Failed to get value from field [" + field + "]", ex);
}
}
/**
* 检查字段是否是public static final修饰符。
*
* @param field 字段对象
* @return 是则返回true,否则false
*/
public static boolean isPublicStaticFinal(Field field) {
int modifiers = field.getModifiers();
return (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers));
}
/**
* 对类及其所有父类中的每个字段执行回调操作。
*
* @param clazz 类对象
* @param fc 回调接口
*/
public static void doWithFields(Class<?> clazz, FieldCallback fc) {
// Keep backing up the inheritance hierarchy.
Class<?> targetClass = clazz;
do {
Field[] fields = getDeclaredFields(targetClass);
for (Field field : fields) {
try {
fc.doWith(field);
} catch (IllegalAccessException ex) {
throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex);
}
}
targetClass = targetClass.getSuperclass();
} while (targetClass != null && targetClass != Object.class);
}
/**
* 字段遍历回调接口,用于自定义字段处理逻辑。
*/
public interface FieldCallback {
/**
* 处理单个字段的操作。
*
* @param field 当前字段对象
*/
void doWith(Field field) throws IllegalArgumentException, IllegalAccessException;
}
// ---------------------- Proxy ----------------------
/**
* 创建一个实现了指定接口的新代理实例。
*
* @param interfaceType 接口类型
* @param handler 方法调用处理器
* @param <T> 泛型参数表示代理类型
* @return 实现了该接口的代理对象
*/
public static <T> T newProxy(Class<T> interfaceType, InvocationHandler handler) {
AssertUtils.notNull(interfaceType, "Interface type must not be null");
AssertUtils.notNull(handler, "InvocationHandler must not be null");
AssertUtils.isTrue(interfaceType.isInterface(), interfaceType + "is not an interface");
Object object = Proxy.newProxyInstance(
interfaceType.getClassLoader(),
new Class<?>[]{
interfaceType
},
handler
);
return interfaceType.cast(object);
}
}
最后修改:2025 年 11 月 14 日
© 允许规范转载