package com.imyeyu.java.ref; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * 反射工具类,提供字段与方法查找、字段读写、字符串转枚举等能力 * * @author 夜雨 * @since 2023-05-04 15:05 */ public class Ref { /** * 获取指定类声明的字段列表(不包含父类) * * @param clazz 类型对象 * @return 字段列表 */ public static List listFields(Class clazz) { return List.of(clazz.getDeclaredFields()); } /** * 获取指定类及其父类声明的字段列表(直到 {@link Object} 之前) * * @param clazz 类型对象 * @return 字段列表 */ public static List listAllFields(Class clazz) { List result = new ArrayList<>(); while (clazz != null && clazz != Object.class) { Collections.addAll(result, clazz.getDeclaredFields()); clazz = clazz.getSuperclass(); } return result; } /** * 将外部键名转换为 Java 字段名 * * @param keyName 外部键名,支持中划线、下划线和空格分隔 * @return 驼峰命名字段名 */ public static String getFieldName(String keyName) { String[] splits = {"-", "_", " "}; StringBuilder full = new StringBuilder(keyName.substring(0, 1).toUpperCase() + keyName.substring(1)); for (String split : splits) { if (keyName.contains(split)) { // 存在分隔符时,先按分隔符拆词,再按驼峰拼接 full.setLength(0); String[] word = keyName.split(split); for (String s : word) { full.append(s.substring(0, 1).toUpperCase()).append(s.substring(1)); } break; } } return String.valueOf(full.charAt(0)).toLowerCase() + full.substring(1); } /** * 反射获取对象字段,包括父级类,直至 {@link Object},如果都不存在则抛出异常 * * @param clazz 类 * @param fieldName 字段名 * @return 字段对象 * @throws NullPointerException 找不到字段时抛出异常 */ public static Field getField(Class clazz, String fieldName) { do { try { Field field = clazz.getDeclaredField(fieldName); field.setAccessible(true); return field; } catch (NoSuchFieldException e) { clazz = clazz.getSuperclass(); } } while (clazz != Object.class); throw new NullPointerException("not found field: %s in %s".formatted(fieldName, clazz)); } /** * 反射获取对象字段值,包括父级类,直至 {@link Object} * * @param object 对象 * @param fieldName 字段名 * @param toClass 返回类 * @param 返回类型 * @return 字段值 * @throws IllegalAccessException 反射访问失败 * @throws NullPointerException 向上反射直至 {@link Object} 也找不到该字段 */ public static T getFieldValue(Object object, String fieldName, Class toClass) throws IllegalAccessException, NullPointerException { return getFieldValue(object, getField(object.getClass(), fieldName), toClass); } /** * 反射获取对象字段值 * * @param object 对象 * @param field 字段 * @param toClass 返回类 * @param 返回类型 * @return 字段值 * @throws IllegalAccessException 反射访问失败 * @throws NullPointerException 字段对象为空 */ public static T getFieldValue(Object object, Field field, Class toClass) throws IllegalAccessException, NullPointerException { if (field == null) { throw new NullPointerException("field can not be null"); } field.setAccessible(true); return toClass.cast(field.get(object)); } /** * 反射获取类字段 * * @param objectClass 类 * @param fieldName 字段名 * @return 字段对象,不存在时返回 null */ public static Field getClassField(Class objectClass, String fieldName) { try { Field field = objectClass.getDeclaredField(fieldName); field.setAccessible(true); return field; } catch (NoSuchFieldException e) { return null; } } /** * 反射获取指定类字段值 * * @param object 对象 * @param objectClass 类 * @param fieldName 字段名 * @param toClass 值类型 * @param 值类型 * @return 字段值 * @throws IllegalAccessException 反射访问失败 * @throws NoSuchFieldException 字段不存在 */ public static T getClassFieldValue(Object object, Class objectClass, String fieldName, Class toClass) throws IllegalAccessException, NoSuchFieldException { Field field = getClassField(objectClass, fieldName); if (field == null) { throw new NoSuchFieldException("not found " + fieldName + " field in " + objectClass.getSimpleName()); } field.setAccessible(true); return toClass.cast(field.get(object)); } /** * 反射设置对象字段值,包括父级类,直至 {@link Object} * * @param object 对象 * @param fieldName 字段名 * @param value 字段值 * @throws IllegalAccessException 反射访问失败 */ public static void setFieldValue(Object object, String fieldName, Object value) throws IllegalAccessException { setFieldValue(object, getField(object.getClass(), fieldName), value); } /** * 反射设置对象字段值 * * @param object 对象 * @param field 字段对象 * @param value 字段值 * @throws IllegalAccessException 反射访问失败 */ public static void setFieldValue(Object object, Field field, Object value) throws IllegalAccessException { field.setAccessible(true); field.set(object, value); } /** * 反射设置对象字段值 * * @param object 对象 * @param objectClass 类 * @param fieldName 字段名 * @param value 字段值 * @throws IllegalAccessException 反射访问失败 * @throws NullPointerException 字段不存在 */ public static void setClassFieldValue(Object object, Class objectClass, String fieldName, Object value) throws IllegalAccessException, NullPointerException { Field field = getClassField(objectClass, fieldName); if (field == null) { throw new NullPointerException("not found " + fieldName + " field in " + objectClass.getSimpleName() + " class"); } field.setAccessible(true); field.set(object, value); } /** * 反射查找方法,包括父级类,直至 {@link Object},如果都不存在则返回 null * * @param clazz 类 * @param methodName 方法名 * @param parameterTypes 可选参 * @return 方法对象,不存在时返回 null * @throws NullPointerException 类对象为空 */ public static Method getMethod(Class clazz, String methodName, Class... parameterTypes) { if (clazz == null) { throw new NullPointerException("class can not be null"); } do { try { Method method = clazz.getDeclaredMethod(methodName, parameterTypes); method.setAccessible(true); return method; } catch (NoSuchMethodException e) { clazz = clazz.getSuperclass(); } } while (clazz != Object.class); return null; } /** * 字符串转枚举 * * @param clazz 枚举类 * @param string 字符串 * @param 泛型 * @return 匹配到的枚举值,找不到或输入为空时返回 null * @throws IllegalArgumentException 传入类型不是枚举类型 */ public static > T toType(Class clazz, String string) { if (string == null) { return null; } T[] ts = clazz.getEnumConstants(); if (ts == null) { throw new IllegalArgumentException(clazz.getName() + " is not an enum type"); } for (T t : ts) { if (t.name().equalsIgnoreCase(string)) { return t; } } return null; } /** * 创建字段反射元信息对象 * * @param owner 字段所属类型 * @param keyName 字段键名 * @return 字段反射元信息 */ public static RefField field(Class owner, String keyName) { return new RefField(owner, keyName); } /** * 通过无参构造器创建实例 * * @param type 类型对象 * @param 泛型类型 * @return 新实例 * @throws Exception 反射创建实例异常 */ public static T newInstance(Class type) throws Exception { return type.getDeclaredConstructor().newInstance(); } }