com.xiaoleilu.hutool.util.ReflectUtil Maven / Gradle / Ivy
package com.xiaoleilu.hutool.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.xiaoleilu.hutool.exceptions.UtilException;
import com.xiaoleilu.hutool.lang.Assert;
import com.xiaoleilu.hutool.lang.Filter;
import com.xiaoleilu.hutool.lang.SimpleCache;
/**
* 反射工具类
*
* @author Looly
* @since 3.0.9
*/
public class ReflectUtil {
/** 构造对象缓存 */
private static final SimpleCache, Constructor>[]> CONSTRUCTORS_CACHE = new SimpleCache<>();
/** 字段缓存 */
private static final SimpleCache, Field[]> FIELDS_CACHE = new SimpleCache<>();
/** 方法缓存 */
private static final SimpleCache, Method[]> METHODS_CACHE = new SimpleCache<>();
// --------------------------------------------------------------------------------------------------------- Constructor
/**
* 查找类中的指定参数的构造方法
*
* @param 对象类型
* @param clazz 类
* @param parameterTypes 参数类型,只要任何一个参数是指定参数的父类或接口或相等即可
* @return 构造方法,如果未找到返回null
*/
@SuppressWarnings("unchecked")
public static Constructor getConstructor(Class clazz, Class>... parameterTypes) {
if (null == clazz) {
return null;
}
final Constructor>[] constructors = clazz.getConstructors();
Class>[] pts;
for (Constructor> constructor : constructors) {
pts = constructor.getParameterTypes();
if (ClassUtil.isAllAssignableFrom(pts, parameterTypes)) {
return (Constructor) constructor;
}
}
return null;
}
/**
* 获得一个类中所有字段列表
*
* @param 构造的对象类型
* @param beanClass 类
* @return 字段列表
* @throws SecurityException 安全检查异常
*/
@SuppressWarnings("unchecked")
public static Constructor[] getConstructors(Class beanClass) throws SecurityException {
Assert.notNull(beanClass);
Constructor>[] constructors = CONSTRUCTORS_CACHE.get(beanClass);
if (null != constructors) {
return (Constructor[]) constructors;
}
constructors = getConstructorsDirectly(beanClass);
return (Constructor[]) CONSTRUCTORS_CACHE.put(beanClass, constructors);
}
/**
* 获得一个类中所有字段列表,直接反射获取,无缓存
*
* @param beanClass 类
* @return 字段列表
* @throws SecurityException 安全检查异常
*/
public static Constructor>[] getConstructorsDirectly(Class> beanClass) throws SecurityException {
Assert.notNull(beanClass);
return beanClass.getDeclaredConstructors();
}
// --------------------------------------------------------------------------------------------------------- Field
/**
* 查找指定类中的所有字段(包括非public字段),也包括父类和Object类的字段, 字段不存在则返回null
*
* @param beanClass 被查找字段的类,不能为null
* @param name 字段名
* @return 字段
* @throws SecurityException 安全异常
*/
public static Field getField(Class> beanClass, String name) throws SecurityException {
final Field[] fields = getFields(beanClass);
if (ArrayUtil.isNotEmpty(fields)) {
for (Field field : fields) {
if ((name.equals(field.getName()))) {
return field;
}
}
}
return null;
}
/**
* 获得一个类中所有字段列表,包括其父类中的字段
*
* @param beanClass 类
* @return 字段列表
* @throws SecurityException 安全检查异常
*/
public static Field[] getFields(Class> beanClass) throws SecurityException {
Field[] allFields = FIELDS_CACHE.get(beanClass);
if (null != allFields) {
return allFields;
}
allFields = getFieldsDirectly(beanClass, true);
return FIELDS_CACHE.put(beanClass, allFields);
}
/**
* 获得一个类中所有字段列表,直接反射获取,无缓存
*
* @param beanClass 类
* @param withSuperClassFieds 是否包括父类的字段列表
* @return 字段列表
* @throws SecurityException 安全检查异常
*/
public static Field[] getFieldsDirectly(Class> beanClass, boolean withSuperClassFieds) throws SecurityException {
Assert.notNull(beanClass);
Field[] allFields = null;
Class> searchType = beanClass;
Field[] declaredFields;
while (searchType != null) {
declaredFields = searchType.getDeclaredFields();
if (null == allFields) {
allFields = declaredFields;
} else {
allFields = ArrayUtil.append(allFields, declaredFields);
}
searchType = withSuperClassFieds ? searchType.getSuperclass() : null;
}
return allFields;
}
/**
* 获取字段值
*
* @param obj 对象
* @param fieldName 字段名
* @return 字段值
* @throws UtilException 包装IllegalAccessException异常
*/
public static Object getFieldValue(Object obj, String fieldName) throws UtilException{
if (null == obj || StrUtil.isBlank(fieldName)) {
return null;
}
return getFieldValue(obj, getField(obj.getClass(), fieldName));
}
/**
* 获取字段值
*
* @param obj 对象
* @param field 字段
* @return 字段值
* @throws UtilException 包装IllegalAccessException异常
*/
public static Object getFieldValue(Object obj, Field field) throws UtilException{
if (null == obj || null == field) {
return null;
}
field.setAccessible(true);
Object result = null;
try {
result = field.get(obj);
} catch (IllegalAccessException e) {
throw new UtilException(e, "IllegalAccess for {}.{}", obj.getClass(), field.getName());
}
return result;
}
/**
* 设置字段值
*
* @param obj 对象
* @param fieldName 字段名
* @param value 值,值类型必须与字段类型匹配,不会自动转换对象类型
* @throws UtilException 包装IllegalAccessException异常
*/
public static void setFieldValue(Object obj, String fieldName, Object value) throws UtilException{
Assert.notNull(obj);
Assert.notBlank(fieldName);
setFieldValue(obj, getField(obj.getClass(), fieldName), value);
}
/**
* 设置字段值
*
* @param obj 对象
* @param field 字段
* @param value 值,值类型必须与字段类型匹配,不会自动转换对象类型
* @throws UtilException UtilException 包装IllegalAccessException异常
*/
public static void setFieldValue(Object obj, Field field, Object value) throws UtilException{
Assert.notNull(obj);
Assert.notNull(field);
field.setAccessible(true);
try {
field.set(obj, value);
} catch (IllegalAccessException e) {
throw new UtilException(e, "IllegalAccess for {}.{}", obj.getClass(), field.getName());
}
}
// --------------------------------------------------------------------------------------------------------- method
/**
* 查找指定对象中的所有方法(包括非public方法),也包括父对象和Object类的方法
*
* @param obj 被查找的对象,如果为{@code null}返回{@code null}
* @param methodName 方法名,如果为空字符串返回{@code null}
* @param args 参数
* @return 方法
* @throws SecurityException 无访问权限抛出异常
*/
public static Method getMethodOfObj(Object obj, String methodName, Object... args) throws SecurityException {
if (null == obj || StrUtil.isBlank(methodName)) {
return null;
}
return getMethod(obj.getClass(), methodName, ClassUtil.getClasses(args));
}
/**
* 忽略大小写查找指定方法,如果找不到对应的方法则返回null
*
* @param clazz 类,如果为{@code null}返回{@code null}
* @param methodName 方法名,如果为空字符串返回{@code null}
* @param paramTypes 参数类型,指定参数类型如果是方法的子类也算
* @return 方法
* @throws SecurityException 无权访问抛出异常
* @since 3.2.0
*/
public static Method getMethodIgnoreCase(Class> clazz, String methodName, Class>... paramTypes) throws SecurityException {
return getMethod(clazz, true, methodName, paramTypes);
}
/**
* 查找指定方法 如果找不到对应的方法则返回null
*
* @param clazz 类,如果为{@code null}返回{@code null}
* @param methodName 方法名,如果为空字符串返回{@code null}
* @param paramTypes 参数类型,指定参数类型如果是方法的子类也算
* @return 方法
* @throws SecurityException 无权访问抛出异常
*/
public static Method getMethod(Class> clazz, String methodName, Class>... paramTypes) throws SecurityException {
return getMethod(clazz, false, methodName, paramTypes);
}
/**
* 查找指定方法 如果找不到对应的方法则返回null
*
* @param clazz 类,如果为{@code null}返回{@code null}
* @param ignoreCase 是否忽略大小写
* @param methodName 方法名,如果为空字符串返回{@code null}
* @param paramTypes 参数类型,指定参数类型如果是方法的子类也算
* @return 方法
* @throws SecurityException 无权访问抛出异常
* @since 3.2.0
*/
public static Method getMethod(Class> clazz, boolean ignoreCase, String methodName, Class>... paramTypes) throws SecurityException {
if (null == clazz || StrUtil.isBlank(methodName)) {
return null;
}
final Method[] methods = getMethods(clazz);
if (ArrayUtil.isNotEmpty(methods)) {
for (Method method : methods) {
if (StrUtil.equals(methodName, method.getName(), ignoreCase)) {
if (ArrayUtil.isEmpty(paramTypes) || ClassUtil.isAllAssignableFrom(method.getParameterTypes(), paramTypes)) {
return method;
}
}
}
}
return null;
}
/**
* 获得指定类中的Public方法名
* 去重重载的方法
*
* @param clazz 类
* @return 方法名Set
* @throws SecurityException 安全异常
*/
public static Set getMethodNames(Class> clazz) throws SecurityException {
final HashSet methodSet = new HashSet();
final Method[] methods = getMethods(clazz);
for (Method method : methods) {
methodSet.add(method.getName());
}
return methodSet;
}
/**
* 获得指定类过滤后的Public方法列表
*
* @param clazz 查找方法的类
* @param filter 过滤器
* @return 过滤后的方法列表
* @throws SecurityException 安全异常
*/
public static Method[] getMethods(Class> clazz, Filter filter) throws SecurityException {
if (null == clazz) {
return null;
}
final Method[] methods = getMethods(clazz);
if (null == filter) {
return methods;
}
final List methodList = new ArrayList<>();
for (Method method : methods) {
if (filter.accept(method)) {
methodList.add(method);
}
}
return methodList.toArray(new Method[methodList.size()]);
}
/**
* 获得一个类中所有方法列表,包括其父类中的方法
*
* @param beanClass 类
* @return 方法列表
* @throws SecurityException 安全检查异常
*/
public static Method[] getMethods(Class> beanClass) throws SecurityException {
Method[] allMethods = METHODS_CACHE.get(beanClass);
if (null != allMethods) {
return allMethods;
}
allMethods = getMethodsDirectly(beanClass, true);
return METHODS_CACHE.put(beanClass, allMethods);
}
/**
* 获得一个类中所有方法列表,直接反射获取,无缓存
*
* @param beanClass 类
* @param withSuperClassMethods 是否包括父类的方法列表
* @return 方法列表
* @throws SecurityException 安全检查异常
*/
public static Method[] getMethodsDirectly(Class> beanClass, boolean withSuperClassMethods) throws SecurityException {
Assert.notNull(beanClass);
Method[] allMethods = null;
Class> searchType = beanClass;
Method[] declaredMethods;
while (searchType != null) {
declaredMethods = searchType.getDeclaredMethods();
if (null == allMethods) {
allMethods = declaredMethods;
} else {
allMethods = ArrayUtil.append(allMethods, declaredMethods);
}
searchType = withSuperClassMethods ? searchType.getSuperclass() : null;
}
return allMethods;
}
/**
* 是否为equals方法
*
* @param method 方法
* @return 是否为equals方法
*/
public static boolean isEqualsMethod(Method method) {
if (method == null || false == method.getName().equals("equals")) {
return false;
}
final Class>[] paramTypes = method.getParameterTypes();
return (1 == paramTypes.length && paramTypes[0] == Object.class);
}
/**
* 是否为hashCode方法
*
* @param method 方法
* @return 是否为hashCode方法
*/
public static boolean isHashCodeMethod(Method method) {
return (method != null && method.getName().equals("hashCode") && method.getParameterTypes().length == 0);
}
/**
* 是否为toString方法
*
* @param method 方法
* @return 是否为toString方法
*/
public static boolean isToStringMethod(Method method) {
return (method != null && method.getName().equals("toString") && method.getParameterTypes().length == 0);
}
// --------------------------------------------------------------------------------------------------------- newInstance
/**
* 实例化对象
*
* @param 对象类型
* @param clazz 类名
* @return 对象
* @throws UtilException 包装各类异常
*/
@SuppressWarnings("unchecked")
public static T newInstance(String clazz) throws UtilException{
try {
return (T) Class.forName(clazz).newInstance();
} catch (Exception e) {
throw new UtilException(StrUtil.format("Instance class [{}] error!", clazz), e);
}
}
/**
* 实例化对象
*
* @param 对象类型
* @param clazz 类
* @param params 构造函数参数
* @return 对象
* @throws UtilException 包装各类异常
*/
public static T newInstance(Class clazz, Object... params) throws UtilException{
if (ArrayUtil.isEmpty(params)) {
try {
return (T) clazz.newInstance();
} catch (Exception e) {
throw new UtilException(StrUtil.format("Instance class [{}] error!", clazz), e);
}
}
final Class>[] paramTypes = ClassUtil.getClasses(params);
final Constructor> constructor = getConstructor(clazz, paramTypes);
if (null == constructor) {
throw new UtilException("No Constructor matched for parameter types: [{}]", new Object[] { paramTypes });
}
try {
return getConstructor(clazz, paramTypes).newInstance(params);
} catch (Exception e) {
throw new UtilException(StrUtil.format("Instance class [{}] error!", clazz), e);
}
}
/**
* 尝试遍历并调用此类的所有构造方法,直到构造成功并返回
*
* @param 对象类型
* @param beanClass 被构造的类
* @return 构造后的对象
*/
public static T newInstanceIfPossible(Class beanClass) {
Assert.notNull(beanClass);
try {
return (T) beanClass.newInstance();
} catch (Exception e) {
//ignore
//默认构造不存在的情况下查找其它构造
}
final Constructor[] constructors = getConstructors(beanClass);
Class>[] parameterTypes;
for (Constructor constructor : constructors) {
parameterTypes = constructor.getParameterTypes();
if(0 == parameterTypes.length) {
continue;
}
try {
constructor.newInstance(ClassUtil.getDefaultValues(parameterTypes));
} catch (Exception e) {
// 构造出错时继续尝试下一种构造方式
continue;
}
}
return null;
}
// --------------------------------------------------------------------------------------------------------- invoke
/**
* 执行静态方法
*
* @param 对象类型
* @param method 方法(对象方法或static方法都可)
* @param args 参数对象
* @return 结果
* @throws UtilException 多种异常包装
*/
public static T invokeStatic(Method method, Object... args) throws UtilException{
return invoke(null, method, args);
}
/**
* 执行方法
*
* @param 返回对象类型
* @param obj 对象,如果执行静态方法,此值为null
* @param method 方法(对象方法或static方法都可)
* @param args 参数对象
* @return 结果
* @throws UtilException 一些列异常的包装
*/
@SuppressWarnings("unchecked")
public static T invoke(Object obj, Method method, Object... args) throws UtilException{
if (false == method.isAccessible()) {
method.setAccessible(true);
}
try {
return (T) method.invoke(ClassUtil.isStatic(method) ? null : obj, args);
} catch (Exception e) {
throw new UtilException(e);
}
}
/**
* 执行对象中指定方法
*
* @param 返回对象类型
* @param obj 方法所在对象
* @param methodName 方法名
* @param args 参数列表
* @return 执行结果
* @throws UtilException IllegalAccessException包装
* @since 3.1.2
*/
public static T invoke(Object obj, String methodName, Object... args) throws UtilException{
final Method method = getMethodOfObj(obj, methodName, args);
if (null == method) {
throw new UtilException(StrUtil.format("No such method: [{}]", methodName));
}
return invoke(obj, method, args);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy