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 日
如果觉得我的文章对你有用,请随意赞赏