Files
timi-java/src/main/java/com/imyeyu/java/ref/Ref.java
T
Timi fecf693578
CI/CD / build-deploy (pull_request) Successful in 17s
v0.0.3
2026-04-27 23:49:37 +08:00

275 lines
8.1 KiB
Java

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<Field> listFields(Class<?> clazz) {
return List.of(clazz.getDeclaredFields());
}
/**
* 获取指定类及其父类声明的字段列表(直到 {@link Object} 之前)
*
* @param clazz 类型对象
* @return 字段列表
*/
public static List<Field> listAllFields(Class<?> clazz) {
List<Field> 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 <T> 返回类型
* @return 字段值
* @throws IllegalAccessException 反射访问失败
* @throws NullPointerException 向上反射直至 {@link Object} 也找不到该字段
*/
public static <T> T getFieldValue(Object object, String fieldName, Class<? extends T> toClass) throws IllegalAccessException, NullPointerException {
return getFieldValue(object, getField(object.getClass(), fieldName), toClass);
}
/**
* 反射获取对象字段值
*
* @param object 对象
* @param field 字段
* @param toClass 返回类
* @param <T> 返回类型
* @return 字段值
* @throws IllegalAccessException 反射访问失败
* @throws NullPointerException 字段对象为空
*/
public static <T> T getFieldValue(Object object, Field field, Class<? extends T> 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 <T> 值类型
* @return 字段值
* @throws IllegalAccessException 反射访问失败
* @throws NoSuchFieldException 字段不存在
*/
public static <T> T getClassFieldValue(Object object, Class<?> objectClass, String fieldName, Class<T> 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 <T> 泛型
* @return 匹配到的枚举值,找不到或输入为空时返回 null
* @throws IllegalArgumentException 传入类型不是枚举类型
*/
public static <T extends Enum<?>> T toType(Class<T> 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 <T> 泛型类型
* @return 新实例
* @throws Exception 反射创建实例异常
*/
public static <T> T newInstance(Class<T> type) throws Exception {
return type.getDeclaredConstructor().newInstance();
}
}