mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add MethodUtil
This commit is contained in:
parent
140e1d546f
commit
6d7d350886
@ -1,6 +1,6 @@
|
|||||||
package cn.hutool.core.annotation;
|
package cn.hutool.core.annotation;
|
||||||
|
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.text.StrUtil;
|
import cn.hutool.core.text.StrUtil;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -71,7 +71,7 @@ public class AnnotationProxy<T extends Annotation> implements Annotation, Invoca
|
|||||||
* @return 属性(方法结果)映射
|
* @return 属性(方法结果)映射
|
||||||
*/
|
*/
|
||||||
private Map<String, Object> initAttributes() {
|
private Map<String, Object> initAttributes() {
|
||||||
final Method[] methods = ReflectUtil.getMethods(this.type);
|
final Method[] methods = MethodUtil.getMethods(this.type);
|
||||||
final Map<String, Object> attributes = new HashMap<>(methods.length, 1);
|
final Map<String, Object> attributes = new HashMap<>(methods.length, 1);
|
||||||
|
|
||||||
for (final Method method : methods) {
|
for (final Method method : methods) {
|
||||||
@ -80,7 +80,7 @@ public class AnnotationProxy<T extends Annotation> implements Annotation, Invoca
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes.put(method.getName(), ReflectUtil.invoke(this.annotation, method));
|
attributes.put(method.getName(), MethodUtil.invoke(this.annotation, method));
|
||||||
}
|
}
|
||||||
|
|
||||||
return attributes;
|
return attributes;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cn.hutool.core.annotation;
|
package cn.hutool.core.annotation;
|
||||||
|
|
||||||
import cn.hutool.core.exceptions.UtilException;
|
import cn.hutool.core.exceptions.UtilException;
|
||||||
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.reflect.ReflectUtil;
|
||||||
|
|
||||||
@ -169,11 +170,11 @@ public class AnnotationUtil {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Method method = ReflectUtil.getMethodOfObj(annotation, propertyName);
|
final Method method = MethodUtil.getMethodOfObj(annotation, propertyName);
|
||||||
if (null == method) {
|
if (null == method) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return ReflectUtil.invoke(annotation, method);
|
return MethodUtil.invoke(annotation, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -191,7 +192,7 @@ public class AnnotationUtil {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Method[] methods = ReflectUtil.getMethods(annotationType, t -> {
|
final Method[] methods = MethodUtil.getMethods(annotationType, t -> {
|
||||||
if (ArrayUtil.isEmpty(t.getParameterTypes())) {
|
if (ArrayUtil.isEmpty(t.getParameterTypes())) {
|
||||||
// 只读取无参方法
|
// 只读取无参方法
|
||||||
final String name = t.getName();
|
final String name = t.getName();
|
||||||
@ -205,7 +206,7 @@ public class AnnotationUtil {
|
|||||||
|
|
||||||
final HashMap<String, Object> result = new HashMap<>(methods.length, 1);
|
final HashMap<String, Object> result = new HashMap<>(methods.length, 1);
|
||||||
for (final Method method : methods) {
|
for (final Method method : methods) {
|
||||||
result.put(method.getName(), ReflectUtil.invoke(annotation, method));
|
result.put(method.getName(), MethodUtil.invoke(annotation, method));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package cn.hutool.core.bean;
|
|||||||
|
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.map.CaseInsensitiveMap;
|
import cn.hutool.core.map.CaseInsensitiveMap;
|
||||||
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.util.BooleanUtil;
|
import cn.hutool.core.util.BooleanUtil;
|
||||||
import cn.hutool.core.reflect.ModifierUtil;
|
import cn.hutool.core.reflect.ModifierUtil;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.reflect.ReflectUtil;
|
||||||
@ -140,7 +141,7 @@ public class BeanDesc implements Serializable {
|
|||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
private BeanDesc init() {
|
private BeanDesc init() {
|
||||||
final Method[] gettersAndSetters = ReflectUtil.getMethods(this.beanClass, ReflectUtil::isGetterOrSetterIgnoreCase);
|
final Method[] gettersAndSetters = MethodUtil.getMethods(this.beanClass, MethodUtil::isGetterOrSetterIgnoreCase);
|
||||||
PropDesc prop;
|
PropDesc prop;
|
||||||
for (final Field field : ReflectUtil.getFields(this.beanClass)) {
|
for (final Field field : ReflectUtil.getFields(this.beanClass)) {
|
||||||
// 排除静态属性和对象子类
|
// 排除静态属性和对象子类
|
||||||
|
@ -3,6 +3,7 @@ package cn.hutool.core.bean;
|
|||||||
import cn.hutool.core.clone.CloneSupport;
|
import cn.hutool.core.clone.CloneSupport;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.reflect.ClassUtil;
|
import cn.hutool.core.reflect.ClassUtil;
|
||||||
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.reflect.ReflectUtil;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -169,7 +170,7 @@ public class DynaBean extends CloneSupport<DynaBean> implements Serializable {
|
|||||||
* @return 执行结果,可能为null
|
* @return 执行结果,可能为null
|
||||||
*/
|
*/
|
||||||
public Object invoke(final String methodName, final Object... params) {
|
public Object invoke(final String methodName, final Object... params) {
|
||||||
return ReflectUtil.invoke(this.bean, methodName, params);
|
return MethodUtil.invoke(this.bean, methodName, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,7 +3,7 @@ package cn.hutool.core.bean;
|
|||||||
import cn.hutool.core.annotation.AnnotationUtil;
|
import cn.hutool.core.annotation.AnnotationUtil;
|
||||||
import cn.hutool.core.annotation.PropIgnore;
|
import cn.hutool.core.annotation.PropIgnore;
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.reflect.ClassUtil;
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.reflect.ModifierUtil;
|
import cn.hutool.core.reflect.ModifierUtil;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.reflect.ReflectUtil;
|
||||||
import cn.hutool.core.reflect.TypeUtil;
|
import cn.hutool.core.reflect.TypeUtil;
|
||||||
@ -43,8 +43,8 @@ public class PropDesc {
|
|||||||
*/
|
*/
|
||||||
public PropDesc(final Field field, final Method getter, final Method setter) {
|
public PropDesc(final Field field, final Method getter, final Method setter) {
|
||||||
this.field = field;
|
this.field = field;
|
||||||
this.getter = ClassUtil.setAccessible(getter);
|
this.getter = ReflectUtil.setAccessible(getter);
|
||||||
this.setter = ClassUtil.setAccessible(setter);
|
this.setter = ReflectUtil.setAccessible(setter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -152,7 +152,7 @@ public class PropDesc {
|
|||||||
*/
|
*/
|
||||||
public Object getValue(final Object bean) {
|
public Object getValue(final Object bean) {
|
||||||
if (null != this.getter) {
|
if (null != this.getter) {
|
||||||
return ReflectUtil.invoke(bean, this.getter);
|
return MethodUtil.invoke(bean, this.getter);
|
||||||
} else if (ModifierUtil.isPublic(this.field)) {
|
} else if (ModifierUtil.isPublic(this.field)) {
|
||||||
return ReflectUtil.getFieldValue(bean, this.field);
|
return ReflectUtil.getFieldValue(bean, this.field);
|
||||||
}
|
}
|
||||||
@ -223,7 +223,7 @@ public class PropDesc {
|
|||||||
*/
|
*/
|
||||||
public PropDesc setValue(final Object bean, final Object value) {
|
public PropDesc setValue(final Object bean, final Object value) {
|
||||||
if (null != this.setter) {
|
if (null != this.setter) {
|
||||||
ReflectUtil.invoke(bean, this.setter, value);
|
MethodUtil.invoke(bean, this.setter, value);
|
||||||
} else if (ModifierUtil.isPublic(this.field)) {
|
} else if (ModifierUtil.isPublic(this.field)) {
|
||||||
ReflectUtil.setFieldValue(bean, this.field, value);
|
ReflectUtil.setFieldValue(bean, this.field, value);
|
||||||
}
|
}
|
||||||
|
@ -140,11 +140,12 @@ public class ClassLoaderUtil {
|
|||||||
* 3、内部类,例如:java.lang.Thread.State会被转为java.lang.Thread$State加载
|
* 3、内部类,例如:java.lang.Thread.State会被转为java.lang.Thread$State加载
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
* @param <T> 目标类的类型
|
||||||
* @param name 类名
|
* @param name 类名
|
||||||
* @return 类名对应的类
|
* @return 类名对应的类
|
||||||
* @throws UtilException 包装{@link ClassNotFoundException},没有类名对应的类时抛出此异常
|
* @throws UtilException 包装{@link ClassNotFoundException},没有类名对应的类时抛出此异常
|
||||||
*/
|
*/
|
||||||
public static Class<?> loadClass(final String name) throws UtilException {
|
public static <T> Class<T> loadClass(final String name) throws UtilException {
|
||||||
return loadClass(name, true);
|
return loadClass(name, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,12 +159,13 @@ public class ClassLoaderUtil {
|
|||||||
* 3、内部类,例如:java.lang.Thread.State会被转为java.lang.Thread$State加载
|
* 3、内部类,例如:java.lang.Thread.State会被转为java.lang.Thread$State加载
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
* @param <T> 目标类的类型
|
||||||
* @param name 类名
|
* @param name 类名
|
||||||
* @param isInitialized 是否初始化类(调用static模块内容和初始化static属性)
|
* @param isInitialized 是否初始化类(调用static模块内容和初始化static属性)
|
||||||
* @return 类名对应的类
|
* @return 类名对应的类
|
||||||
* @throws UtilException 包装{@link ClassNotFoundException},没有类名对应的类时抛出此异常
|
* @throws UtilException 包装{@link ClassNotFoundException},没有类名对应的类时抛出此异常
|
||||||
*/
|
*/
|
||||||
public static Class<?> loadClass(final String name, final boolean isInitialized) throws UtilException {
|
public static <T> Class<T> loadClass(final String name, final boolean isInitialized) throws UtilException {
|
||||||
return loadClass(name, null, isInitialized);
|
return loadClass(name, null, isInitialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +187,8 @@ public class ClassLoaderUtil {
|
|||||||
* @return 类名对应的类
|
* @return 类名对应的类
|
||||||
* @throws UtilException 包装{@link ClassNotFoundException},没有类名对应的类时抛出此异常
|
* @throws UtilException 包装{@link ClassNotFoundException},没有类名对应的类时抛出此异常
|
||||||
*/
|
*/
|
||||||
public static Class<?> loadClass(String name, ClassLoader classLoader, final boolean isInitialized) throws UtilException {
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> Class<T> loadClass(String name, ClassLoader classLoader, final boolean isInitialized) throws UtilException {
|
||||||
Assert.notNull(name, "Name must not be null");
|
Assert.notNull(name, "Name must not be null");
|
||||||
|
|
||||||
// 自动将包名中的"/"替换为"."
|
// 自动将包名中的"/"替换为"."
|
||||||
@ -201,7 +204,7 @@ public class ClassLoaderUtil {
|
|||||||
final ClassLoader finalClassLoader = classLoader;
|
final ClassLoader finalClassLoader = classLoader;
|
||||||
clazz = CLASS_CACHE.computeIfAbsent(Pair.of(name, classLoader), (key)-> doLoadClass(finalName, finalClassLoader, isInitialized));
|
clazz = CLASS_CACHE.computeIfAbsent(Pair.of(name, classLoader), (key)-> doLoadClass(finalName, finalClassLoader, isInitialized));
|
||||||
}
|
}
|
||||||
return clazz;
|
return (Class<T>) clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,7 +3,7 @@ package cn.hutool.core.classloader;
|
|||||||
import cn.hutool.core.exceptions.UtilException;
|
import cn.hutool.core.exceptions.UtilException;
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.net.URLUtil;
|
import cn.hutool.core.net.URLUtil;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -53,12 +53,12 @@ public class JarClassLoader extends URLClassLoader {
|
|||||||
*/
|
*/
|
||||||
public static void loadJar(final URLClassLoader loader, final File jarFile) throws UtilException {
|
public static void loadJar(final URLClassLoader loader, final File jarFile) throws UtilException {
|
||||||
try {
|
try {
|
||||||
final Method method = ReflectUtil.getMethod(URLClassLoader.class, "addURL", URL.class);
|
final Method method = MethodUtil.getMethod(URLClassLoader.class, "addURL", URL.class);
|
||||||
if (null != method) {
|
if (null != method) {
|
||||||
method.setAccessible(true);
|
method.setAccessible(true);
|
||||||
final List<File> jars = loopJar(jarFile);
|
final List<File> jars = loopJar(jarFile);
|
||||||
for (final File jar : jars) {
|
for (final File jar : jars) {
|
||||||
ReflectUtil.invoke(loader, method, jar.toURI().toURL());
|
MethodUtil.invoke(loader, method, jar.toURI().toURL());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package cn.hutool.core.clone;
|
package cn.hutool.core.clone;
|
||||||
|
|
||||||
|
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 克隆默认实现接口,用于实现返回指定泛型类型的克隆方法
|
* 克隆默认实现接口,用于实现返回指定泛型类型的克隆方法
|
||||||
@ -18,7 +18,7 @@ public interface DefaultCloneable<T> extends java.lang.Cloneable {
|
|||||||
*/
|
*/
|
||||||
default T clone0() {
|
default T clone0() {
|
||||||
try {
|
try {
|
||||||
return ReflectUtil.invoke(this, "clone");
|
return MethodUtil.invoke(this, "clone");
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
throw new CloneRuntimeException(e);
|
throw new CloneRuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import cn.hutool.core.lang.func.Filter;
|
|||||||
import cn.hutool.core.lang.func.Matcher;
|
import cn.hutool.core.lang.func.Matcher;
|
||||||
import cn.hutool.core.lang.func.Func1;
|
import cn.hutool.core.lang.func.Func1;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.text.StrJoiner;
|
import cn.hutool.core.text.StrJoiner;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.util.ObjUtil;
|
import cn.hutool.core.util.ObjUtil;
|
||||||
@ -1046,7 +1047,7 @@ public class IterUtil {
|
|||||||
|
|
||||||
// 反射获取
|
// 反射获取
|
||||||
try {
|
try {
|
||||||
final Object iterator = ReflectUtil.invoke(obj, "iterator");
|
final Object iterator = MethodUtil.invoke(obj, "iterator");
|
||||||
if (iterator instanceof Iterator) {
|
if (iterator instanceof Iterator) {
|
||||||
return (Iterator<?>) iterator;
|
return (Iterator<?>) iterator;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
package cn.hutool.core.convert;
|
package cn.hutool.core.convert;
|
||||||
|
|
||||||
|
import cn.hutool.core.classloader.ClassLoaderUtil;
|
||||||
|
import cn.hutool.core.codec.HexUtil;
|
||||||
import cn.hutool.core.convert.impl.CollectionConverter;
|
import cn.hutool.core.convert.impl.CollectionConverter;
|
||||||
import cn.hutool.core.convert.impl.EnumConverter;
|
import cn.hutool.core.convert.impl.EnumConverter;
|
||||||
import cn.hutool.core.convert.impl.MapConverter;
|
import cn.hutool.core.convert.impl.MapConverter;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.reflect.TypeReference;
|
import cn.hutool.core.reflect.TypeReference;
|
||||||
|
import cn.hutool.core.text.StrUtil;
|
||||||
import cn.hutool.core.text.UnicodeUtil;
|
import cn.hutool.core.text.UnicodeUtil;
|
||||||
import cn.hutool.core.util.ByteUtil;
|
import cn.hutool.core.util.ByteUtil;
|
||||||
import cn.hutool.core.util.CharUtil;
|
import cn.hutool.core.util.CharUtil;
|
||||||
import cn.hutool.core.util.CharsetUtil;
|
import cn.hutool.core.util.CharsetUtil;
|
||||||
import cn.hutool.core.reflect.ClassUtil;
|
|
||||||
import cn.hutool.core.codec.HexUtil;
|
|
||||||
import cn.hutool.core.text.StrUtil;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@ -627,7 +627,7 @@ public class Convert {
|
|||||||
* @throws ConvertException 转换器不存在
|
* @throws ConvertException 转换器不存在
|
||||||
*/
|
*/
|
||||||
public static <T> T convertByClassName(final String className, final Object value) throws ConvertException{
|
public static <T> T convertByClassName(final String className, final Object value) throws ConvertException{
|
||||||
return convert(ClassUtil.loadClass(className), value);
|
return convert(ClassLoaderUtil.loadClass(className), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,9 +6,9 @@ import cn.hutool.core.lang.EnumItem;
|
|||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.map.WeakConcurrentMap;
|
import cn.hutool.core.map.WeakConcurrentMap;
|
||||||
import cn.hutool.core.reflect.ClassUtil;
|
import cn.hutool.core.reflect.ClassUtil;
|
||||||
import cn.hutool.core.util.EnumUtil;
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.reflect.ModifierUtil;
|
import cn.hutool.core.reflect.ModifierUtil;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.util.EnumUtil;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -96,7 +96,7 @@ public class EnumConverter extends AbstractConverter<Object> {
|
|||||||
final Class<?> valueClass = value.getClass();
|
final Class<?> valueClass = value.getClass();
|
||||||
for (final Map.Entry<Class<?>, Method> entry : methodMap.entrySet()) {
|
for (final Map.Entry<Class<?>, Method> entry : methodMap.entrySet()) {
|
||||||
if (ClassUtil.isAssignable(entry.getKey(), valueClass)) {
|
if (ClassUtil.isAssignable(entry.getKey(), valueClass)) {
|
||||||
return ReflectUtil.invokeStatic(entry.getValue(), value);
|
return MethodUtil.invokeStatic(entry.getValue(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package cn.hutool.core.io.resource;
|
package cn.hutool.core.io.resource;
|
||||||
|
|
||||||
import cn.hutool.core.lang.Assert;
|
|
||||||
import cn.hutool.core.classloader.ClassLoaderUtil;
|
import cn.hutool.core.classloader.ClassLoaderUtil;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
@ -63,22 +63,22 @@ public class VfsResource implements Resource {
|
|||||||
* @return 文件是否存在
|
* @return 文件是否存在
|
||||||
*/
|
*/
|
||||||
public boolean exists() {
|
public boolean exists() {
|
||||||
return ReflectUtil.invoke(virtualFile, VIRTUAL_FILE_METHOD_EXISTS);
|
return MethodUtil.invoke(virtualFile, VIRTUAL_FILE_METHOD_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return ReflectUtil.invoke(virtualFile, VIRTUAL_FILE_METHOD_GET_NAME);
|
return MethodUtil.invoke(virtualFile, VIRTUAL_FILE_METHOD_GET_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URL getUrl() {
|
public URL getUrl() {
|
||||||
return ReflectUtil.invoke(virtualFile, VIRTUAL_FILE_METHOD_TO_URL);
|
return MethodUtil.invoke(virtualFile, VIRTUAL_FILE_METHOD_TO_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InputStream getStream() {
|
public InputStream getStream() {
|
||||||
return ReflectUtil.invoke(virtualFile, VIRTUAL_FILE_METHOD_GET_INPUT_STREAM);
|
return MethodUtil.invoke(virtualFile, VIRTUAL_FILE_METHOD_GET_INPUT_STREAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -92,7 +92,7 @@ public class VfsResource implements Resource {
|
|||||||
* @return 最后修改时间
|
* @return 最后修改时间
|
||||||
*/
|
*/
|
||||||
public long getLastModified() {
|
public long getLastModified() {
|
||||||
return ReflectUtil.invoke(virtualFile, VIRTUAL_FILE_METHOD_GET_LAST_MODIFIED);
|
return MethodUtil.invoke(virtualFile, VIRTUAL_FILE_METHOD_GET_LAST_MODIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,7 +101,7 @@ public class VfsResource implements Resource {
|
|||||||
* @return VFS文件大小
|
* @return VFS文件大小
|
||||||
*/
|
*/
|
||||||
public long size() {
|
public long size() {
|
||||||
return ReflectUtil.invoke(virtualFile, VIRTUAL_FILE_METHOD_GET_SIZE);
|
return MethodUtil.invoke(virtualFile, VIRTUAL_FILE_METHOD_GET_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package cn.hutool.core.lang;
|
package cn.hutool.core.lang;
|
||||||
|
|
||||||
|
import cn.hutool.core.classloader.ClassLoaderUtil;
|
||||||
import cn.hutool.core.lang.func.Func0;
|
import cn.hutool.core.lang.func.Func0;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
|
||||||
import cn.hutool.core.reflect.ClassUtil;
|
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.reflect.ReflectUtil;
|
||||||
import cn.hutool.core.text.StrUtil;
|
import cn.hutool.core.text.StrUtil;
|
||||||
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@ -66,7 +66,7 @@ public final class Singleton {
|
|||||||
*/
|
*/
|
||||||
public static <T> T get(final String className, final Object... params) {
|
public static <T> T get(final String className, final Object... params) {
|
||||||
Assert.notBlank(className, "Class name must be not blank !");
|
Assert.notBlank(className, "Class name must be not blank !");
|
||||||
final Class<T> clazz = ClassUtil.loadClass(className);
|
final Class<T> clazz = ClassLoaderUtil.loadClass(className);
|
||||||
return get(clazz, params);
|
return get(clazz, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package cn.hutool.core.lang.func;
|
package cn.hutool.core.lang.func;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.classloader.ClassLoaderUtil;
|
||||||
import cn.hutool.core.map.WeakConcurrentMap;
|
import cn.hutool.core.map.WeakConcurrentMap;
|
||||||
import cn.hutool.core.reflect.ClassUtil;
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
|
||||||
import cn.hutool.core.text.StrUtil;
|
import cn.hutool.core.text.StrUtil;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -57,7 +57,7 @@ public class LambdaUtil {
|
|||||||
public static <R> Class<R> getRealClass(final Func0<?> func) {
|
public static <R> Class<R> getRealClass(final Func0<?> func) {
|
||||||
final SerializedLambda lambda = resolve(func);
|
final SerializedLambda lambda = resolve(func);
|
||||||
checkLambdaTypeCanGetClass(lambda.getImplMethodKind());
|
checkLambdaTypeCanGetClass(lambda.getImplMethodKind());
|
||||||
return ClassUtil.loadClass(lambda.getImplClass());
|
return ClassLoaderUtil.loadClass(lambda.getImplClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,7 +134,7 @@ public class LambdaUtil {
|
|||||||
final SerializedLambda lambda = resolve(func);
|
final SerializedLambda lambda = resolve(func);
|
||||||
checkLambdaTypeCanGetClass(lambda.getImplMethodKind());
|
checkLambdaTypeCanGetClass(lambda.getImplMethodKind());
|
||||||
final String instantiatedMethodType = lambda.getInstantiatedMethodType();
|
final String instantiatedMethodType = lambda.getInstantiatedMethodType();
|
||||||
return ClassUtil.loadClass(StrUtil.sub(instantiatedMethodType, 2, StrUtil.indexOf(instantiatedMethodType, ';')));
|
return ClassLoaderUtil.loadClass(StrUtil.sub(instantiatedMethodType, 2, StrUtil.indexOf(instantiatedMethodType, ';')));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -202,7 +202,7 @@ public class LambdaUtil {
|
|||||||
* @return 返回解析后的结果
|
* @return 返回解析后的结果
|
||||||
*/
|
*/
|
||||||
private static SerializedLambda _resolve(final Serializable func) {
|
private static SerializedLambda _resolve(final Serializable func) {
|
||||||
return cache.computeIfAbsent(func.getClass().getName(), (key) -> ReflectUtil.invoke(func, "writeReplace"));
|
return cache.computeIfAbsent(func.getClass().getName(), (key) -> MethodUtil.invoke(func, "writeReplace"));
|
||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,7 @@ import cn.hutool.core.convert.BasicType;
|
|||||||
import cn.hutool.core.exceptions.UtilException;
|
import cn.hutool.core.exceptions.UtilException;
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.io.resource.ResourceUtil;
|
import cn.hutool.core.io.resource.ResourceUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
|
||||||
import cn.hutool.core.lang.ClassScanner;
|
import cn.hutool.core.lang.ClassScanner;
|
||||||
import cn.hutool.core.lang.Singleton;
|
|
||||||
import cn.hutool.core.net.URLDecoder;
|
import cn.hutool.core.net.URLDecoder;
|
||||||
import cn.hutool.core.net.URLUtil;
|
import cn.hutool.core.net.URLUtil;
|
||||||
import cn.hutool.core.text.StrUtil;
|
import cn.hutool.core.text.StrUtil;
|
||||||
@ -18,7 +16,6 @@ import cn.hutool.core.util.CharsetUtil;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
@ -358,124 +355,6 @@ public class ClassUtil {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 加载类
|
|
||||||
*
|
|
||||||
* @param <T> 对象类型
|
|
||||||
* @param className 类名
|
|
||||||
* @param isInitialized 是否初始化
|
|
||||||
* @return 类
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static <T> Class<T> loadClass(final String className, final boolean isInitialized) {
|
|
||||||
return (Class<T>) ClassLoaderUtil.loadClass(className, isInitialized);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加载类并初始化
|
|
||||||
*
|
|
||||||
* @param <T> 对象类型
|
|
||||||
* @param className 类名
|
|
||||||
* @return 类
|
|
||||||
*/
|
|
||||||
public static <T> Class<T> loadClass(final String className) {
|
|
||||||
return loadClass(className, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------------- Invoke start
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行方法<br>
|
|
||||||
* 可执行Private方法,也可执行static方法<br>
|
|
||||||
* 执行非static方法时,必须满足对象有默认构造方法<br>
|
|
||||||
* 非单例模式,如果是非静态方法,每次创建一个新对象
|
|
||||||
*
|
|
||||||
* @param <T> 对象类型
|
|
||||||
* @param classNameWithMethodName 类名和方法名表达式,类名与方法名用{@code .}或{@code #}连接 例如:com.xiaoleilu.hutool.StrUtil.isEmpty 或 com.xiaoleilu.hutool.StrUtil#isEmpty
|
|
||||||
* @param args 参数,必须严格对应指定方法的参数类型和数量
|
|
||||||
* @return 返回结果
|
|
||||||
*/
|
|
||||||
public static <T> T invoke(final String classNameWithMethodName, final Object[] args) {
|
|
||||||
return invoke(classNameWithMethodName, false, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行方法<br>
|
|
||||||
* 可执行Private方法,也可执行static方法<br>
|
|
||||||
* 执行非static方法时,必须满足对象有默认构造方法<br>
|
|
||||||
*
|
|
||||||
* @param <T> 对象类型
|
|
||||||
* @param classNameWithMethodName 类名和方法名表达式,例如:com.xiaoleilu.hutool.StrUtil#isEmpty或com.xiaoleilu.hutool.StrUtil.isEmpty
|
|
||||||
* @param isSingleton 是否为单例对象,如果此参数为false,每次执行方法时创建一个新对象
|
|
||||||
* @param args 参数,必须严格对应指定方法的参数类型和数量
|
|
||||||
* @return 返回结果
|
|
||||||
*/
|
|
||||||
public static <T> T invoke(final String classNameWithMethodName, final boolean isSingleton, final Object... args) {
|
|
||||||
if (StrUtil.isBlank(classNameWithMethodName)) {
|
|
||||||
throw new UtilException("Blank classNameDotMethodName!");
|
|
||||||
}
|
|
||||||
|
|
||||||
int splitIndex = classNameWithMethodName.lastIndexOf('#');
|
|
||||||
if (splitIndex <= 0) {
|
|
||||||
splitIndex = classNameWithMethodName.lastIndexOf('.');
|
|
||||||
}
|
|
||||||
if (splitIndex <= 0) {
|
|
||||||
throw new UtilException("Invalid classNameWithMethodName [{}]!", classNameWithMethodName);
|
|
||||||
}
|
|
||||||
|
|
||||||
final String className = classNameWithMethodName.substring(0, splitIndex);
|
|
||||||
final String methodName = classNameWithMethodName.substring(splitIndex + 1);
|
|
||||||
|
|
||||||
return invoke(className, methodName, isSingleton, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行方法<br>
|
|
||||||
* 可执行Private方法,也可执行static方法<br>
|
|
||||||
* 执行非static方法时,必须满足对象有默认构造方法<br>
|
|
||||||
* 非单例模式,如果是非静态方法,每次创建一个新对象
|
|
||||||
*
|
|
||||||
* @param <T> 对象类型
|
|
||||||
* @param className 类名,完整类路径
|
|
||||||
* @param methodName 方法名
|
|
||||||
* @param args 参数,必须严格对应指定方法的参数类型和数量
|
|
||||||
* @return 返回结果
|
|
||||||
*/
|
|
||||||
public static <T> T invoke(final String className, final String methodName, final Object[] args) {
|
|
||||||
return invoke(className, methodName, false, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行方法<br>
|
|
||||||
* 可执行Private方法,也可执行static方法<br>
|
|
||||||
* 执行非static方法时,必须满足对象有默认构造方法<br>
|
|
||||||
*
|
|
||||||
* @param <T> 对象类型
|
|
||||||
* @param className 类名,完整类路径
|
|
||||||
* @param methodName 方法名
|
|
||||||
* @param isSingleton 是否为单例对象,如果此参数为false,每次执行方法时创建一个新对象
|
|
||||||
* @param args 参数,必须严格对应指定方法的参数类型和数量
|
|
||||||
* @return 返回结果
|
|
||||||
*/
|
|
||||||
public static <T> T invoke(final String className, final String methodName, final boolean isSingleton, final Object... args) {
|
|
||||||
final Class<Object> clazz = loadClass(className);
|
|
||||||
try {
|
|
||||||
final Method method = ReflectUtil.getMethod(clazz, methodName, getClasses(args));
|
|
||||||
if (null == method) {
|
|
||||||
throw new NoSuchMethodException(StrUtil.format("No such method: [{}]", methodName));
|
|
||||||
}
|
|
||||||
if (isStatic(method)) {
|
|
||||||
return ReflectUtil.invoke(null, method, args);
|
|
||||||
} else {
|
|
||||||
return ReflectUtil.invoke(isSingleton ? Singleton.get(clazz) : clazz.newInstance(), method, args);
|
|
||||||
}
|
|
||||||
} catch (final Exception e) {
|
|
||||||
throw new UtilException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------------- Invoke end
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否为包装类型
|
* 是否为包装类型
|
||||||
*
|
*
|
||||||
@ -580,74 +459,6 @@ public class ClassUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 指定类是否为Public
|
|
||||||
*
|
|
||||||
* @param clazz 类
|
|
||||||
* @return 是否为public
|
|
||||||
*/
|
|
||||||
public static boolean isPublic(final Class<?> clazz) {
|
|
||||||
if (null == clazz) {
|
|
||||||
throw new NullPointerException("Class to provided is null.");
|
|
||||||
}
|
|
||||||
return Modifier.isPublic(clazz.getModifiers());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 指定方法是否为Public
|
|
||||||
*
|
|
||||||
* @param method 方法
|
|
||||||
* @return 是否为public
|
|
||||||
*/
|
|
||||||
public static boolean isPublic(final Method method) {
|
|
||||||
Assert.notNull(method, "Method to provided is null.");
|
|
||||||
return Modifier.isPublic(method.getModifiers());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 指定类是否为非public
|
|
||||||
*
|
|
||||||
* @param clazz 类
|
|
||||||
* @return 是否为非public
|
|
||||||
*/
|
|
||||||
public static boolean isNotPublic(final Class<?> clazz) {
|
|
||||||
return false == isPublic(clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 指定方法是否为非public
|
|
||||||
*
|
|
||||||
* @param method 方法
|
|
||||||
* @return 是否为非public
|
|
||||||
*/
|
|
||||||
public static boolean isNotPublic(final Method method) {
|
|
||||||
return false == isPublic(method);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否为静态方法
|
|
||||||
*
|
|
||||||
* @param method 方法
|
|
||||||
* @return 是否为静态方法
|
|
||||||
*/
|
|
||||||
public static boolean isStatic(final Method method) {
|
|
||||||
Assert.notNull(method, "Method to provided is null.");
|
|
||||||
return Modifier.isStatic(method.getModifiers());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置方法为可访问
|
|
||||||
*
|
|
||||||
* @param method 方法
|
|
||||||
* @return 方法
|
|
||||||
*/
|
|
||||||
public static Method setAccessible(final Method method) {
|
|
||||||
if (null != method && false == method.isAccessible()) {
|
|
||||||
method.setAccessible(true);
|
|
||||||
}
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否为抽象类
|
* 是否为抽象类
|
||||||
*
|
*
|
||||||
|
@ -14,7 +14,7 @@ import java.lang.reflect.Method;
|
|||||||
* 方法句柄是一个有类型的,可以直接执行的指向底层方法、构造器、field等的引用,可以简单理解为函数指针,它是一种更加底层的查找、调整和调用方法的机制。
|
* 方法句柄是一个有类型的,可以直接执行的指向底层方法、构造器、field等的引用,可以简单理解为函数指针,它是一种更加底层的查找、调整和调用方法的机制。
|
||||||
* 参考:
|
* 参考:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>https://stackoverflow.com/questions/22614746/how-do-i-invoke-java-8-default-methods-reflectively</li>
|
* <li><a href="https://stackoverflow.com/questions/22614746/how-do-i-invoke-java-8-default-methods-reflectively">https://stackoverflow.com/questions/22614746/how-do-i-invoke-java-8-default-methods-reflectively</a></li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
@ -138,7 +138,7 @@ public class MethodHandleUtil {
|
|||||||
Assert.notNull(obj, "Object to get method must be not null!");
|
Assert.notNull(obj, "Object to get method must be not null!");
|
||||||
Assert.notBlank(methodName, "Method name must be not blank!");
|
Assert.notBlank(methodName, "Method name must be not blank!");
|
||||||
|
|
||||||
final Method method = ReflectUtil.getMethodOfObj(obj, methodName, args);
|
final Method method = MethodUtil.getMethodOfObj(obj, methodName, args);
|
||||||
if (null == method) {
|
if (null == method) {
|
||||||
throw new UtilException("No such method: [{}] from [{}]", methodName, obj.getClass());
|
throw new UtilException("No such method: [{}] from [{}]", methodName, obj.getClass());
|
||||||
}
|
}
|
||||||
|
734
hutool-core/src/main/java/cn/hutool/core/reflect/MethodUtil.java
Normal file
734
hutool-core/src/main/java/cn/hutool/core/reflect/MethodUtil.java
Normal file
@ -0,0 +1,734 @@
|
|||||||
|
package cn.hutool.core.reflect;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.NullWrapperBean;
|
||||||
|
import cn.hutool.core.classloader.ClassLoaderUtil;
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.collection.UniqueKeySet;
|
||||||
|
import cn.hutool.core.convert.Convert;
|
||||||
|
import cn.hutool.core.exceptions.UtilException;
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.hutool.core.lang.Singleton;
|
||||||
|
import cn.hutool.core.lang.func.Filter;
|
||||||
|
import cn.hutool.core.map.WeakConcurrentMap;
|
||||||
|
import cn.hutool.core.text.StrUtil;
|
||||||
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class MethodUtil {
|
||||||
|
/**
|
||||||
|
* 方法缓存
|
||||||
|
*/
|
||||||
|
private static final WeakConcurrentMap<Class<?>, Method[]> METHODS_CACHE = new WeakConcurrentMap<>();
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------------------- method
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定类本类及其父类中的Public方法名<br>
|
||||||
|
* 去重重载的方法
|
||||||
|
*
|
||||||
|
* @param clazz 类
|
||||||
|
* @return 方法名Set
|
||||||
|
*/
|
||||||
|
public static Set<String> getPublicMethodNames(final Class<?> clazz) {
|
||||||
|
final HashSet<String> methodSet = new HashSet<>();
|
||||||
|
final Method[] methodArray = getPublicMethods(clazz);
|
||||||
|
if (ArrayUtil.isNotEmpty(methodArray)) {
|
||||||
|
for (final Method method : methodArray) {
|
||||||
|
methodSet.add(method.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return methodSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得本类及其父类所有Public方法
|
||||||
|
*
|
||||||
|
* @param clazz 查找方法的类
|
||||||
|
* @return 过滤后的方法列表
|
||||||
|
*/
|
||||||
|
public static Method[] getPublicMethods(final Class<?> clazz) {
|
||||||
|
return null == clazz ? null : clazz.getMethods();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定类过滤后的Public方法列表<br>
|
||||||
|
*
|
||||||
|
* @param clazz 查找方法的类
|
||||||
|
* @param filter 过滤器
|
||||||
|
* @return 过滤后的方法数组
|
||||||
|
*/
|
||||||
|
public static Method[] getPublicMethods(final Class<?> clazz, final Filter<Method> filter) {
|
||||||
|
if (null == clazz) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Method[] methods = getPublicMethods(clazz);
|
||||||
|
if(null == filter){
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ArrayUtil.filter(methods, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定类过滤后的Public方法列表
|
||||||
|
*
|
||||||
|
* @param clazz 查找方法的类
|
||||||
|
* @param excludeMethods 不包括的方法
|
||||||
|
* @return 过滤后的方法列表
|
||||||
|
*/
|
||||||
|
public static Method[] getPublicMethods(final Class<?> clazz, final Method... excludeMethods) {
|
||||||
|
final HashSet<Method> excludeMethodSet = CollUtil.newHashSet(excludeMethods);
|
||||||
|
return getPublicMethods(clazz, method -> false == excludeMethodSet.contains(method));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定类过滤后的Public方法列表
|
||||||
|
*
|
||||||
|
* @param clazz 查找方法的类
|
||||||
|
* @param excludeMethodNames 不包括的方法名列表
|
||||||
|
* @return 过滤后的方法数组
|
||||||
|
*/
|
||||||
|
public static Method[] getPublicMethods(final Class<?> clazz, final String... excludeMethodNames) {
|
||||||
|
final HashSet<String> excludeMethodNameSet = CollUtil.newHashSet(excludeMethodNames);
|
||||||
|
return getPublicMethods(clazz, method -> false == excludeMethodNameSet.contains(method.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找指定Public方法 如果找不到对应的方法或方法不为public的则返回{@code null}
|
||||||
|
*
|
||||||
|
* @param clazz 类
|
||||||
|
* @param methodName 方法名
|
||||||
|
* @param paramTypes 参数类型
|
||||||
|
* @return 方法
|
||||||
|
* @throws SecurityException 无权访问抛出异常
|
||||||
|
*/
|
||||||
|
public static Method getPublicMethod(final Class<?> clazz, final String methodName, final Class<?>... paramTypes) throws SecurityException {
|
||||||
|
try {
|
||||||
|
return clazz.getMethod(methodName, paramTypes);
|
||||||
|
} catch (final NoSuchMethodException ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找指定对象中的所有方法(包括非public方法),也包括父对象和Object类的方法
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 此方法为精准获取方法名,即方法名和参数数量和类型必须一致,否则返回{@code null}。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param obj 被查找的对象,如果为{@code null}返回{@code null}
|
||||||
|
* @param methodName 方法名,如果为空字符串返回{@code null}
|
||||||
|
* @param args 参数
|
||||||
|
* @return 方法
|
||||||
|
* @throws SecurityException 无访问权限抛出异常
|
||||||
|
*/
|
||||||
|
public static Method getMethodOfObj(final Object obj, final String methodName, final Object... args) throws SecurityException {
|
||||||
|
if (null == obj || StrUtil.isBlank(methodName)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return getMethod(obj.getClass(), methodName, ClassUtil.getClasses(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 忽略大小写查找指定方法,如果找不到对应的方法则返回{@code null}
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 此方法为精准获取方法名,即方法名和参数数量和类型必须一致,否则返回{@code null}。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param clazz 类,如果为{@code null}返回{@code null}
|
||||||
|
* @param methodName 方法名,如果为空字符串返回{@code null}
|
||||||
|
* @param paramTypes 参数类型,指定参数类型如果是方法的子类也算
|
||||||
|
* @return 方法
|
||||||
|
* @throws SecurityException 无权访问抛出异常
|
||||||
|
* @since 3.2.0
|
||||||
|
*/
|
||||||
|
public static Method getMethodIgnoreCase(final Class<?> clazz, final String methodName, final Class<?>... paramTypes) throws SecurityException {
|
||||||
|
return getMethod(clazz, true, methodName, paramTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找指定方法 如果找不到对应的方法则返回{@code null}
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 此方法为精准获取方法名,即方法名和参数数量和类型必须一致,否则返回{@code null}。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param clazz 类,如果为{@code null}返回{@code null}
|
||||||
|
* @param methodName 方法名,如果为空字符串返回{@code null}
|
||||||
|
* @param paramTypes 参数类型,指定参数类型如果是方法的子类也算
|
||||||
|
* @return 方法
|
||||||
|
* @throws SecurityException 无权访问抛出异常
|
||||||
|
*/
|
||||||
|
public static Method getMethod(final Class<?> clazz, final String methodName, final Class<?>... paramTypes) throws SecurityException {
|
||||||
|
return getMethod(clazz, false, methodName, paramTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找指定方法 如果找不到对应的方法则返回{@code null}<br>
|
||||||
|
* 此方法为精准获取方法名,即方法名和参数数量和类型必须一致,否则返回{@code null}。<br>
|
||||||
|
* 如果查找的方法有多个同参数类型重载,查找第一个找到的方法
|
||||||
|
*
|
||||||
|
* @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(final Class<?> clazz, final boolean ignoreCase, final String methodName, final Class<?>... paramTypes) throws SecurityException {
|
||||||
|
if (null == clazz || StrUtil.isBlank(methodName)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Method[] methods = getMethods(clazz);
|
||||||
|
if (ArrayUtil.isNotEmpty(methods)) {
|
||||||
|
for (final Method method : methods) {
|
||||||
|
if (StrUtil.equals(methodName, method.getName(), ignoreCase)
|
||||||
|
&& ClassUtil.isAllAssignableFrom(method.getParameterTypes(), paramTypes)
|
||||||
|
//排除桥接方法,pr#1965@Github
|
||||||
|
&& false == method.isBridge()) {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按照方法名查找指定方法名的方法,只返回匹配到的第一个方法,如果找不到对应的方法则返回{@code null}
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 此方法只检查方法名是否一致,并不检查参数的一致性。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param clazz 类,如果为{@code null}返回{@code null}
|
||||||
|
* @param methodName 方法名,如果为空字符串返回{@code null}
|
||||||
|
* @return 方法
|
||||||
|
* @throws SecurityException 无权访问抛出异常
|
||||||
|
* @since 4.3.2
|
||||||
|
*/
|
||||||
|
public static Method getMethodByName(final Class<?> clazz, final String methodName) throws SecurityException {
|
||||||
|
return getMethodByName(clazz, false, methodName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按照方法名查找指定方法名的方法,只返回匹配到的第一个方法,如果找不到对应的方法则返回{@code null}
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 此方法只检查方法名是否一致(忽略大小写),并不检查参数的一致性。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param clazz 类,如果为{@code null}返回{@code null}
|
||||||
|
* @param methodName 方法名,如果为空字符串返回{@code null}
|
||||||
|
* @return 方法
|
||||||
|
* @throws SecurityException 无权访问抛出异常
|
||||||
|
* @since 4.3.2
|
||||||
|
*/
|
||||||
|
public static Method getMethodByNameIgnoreCase(final Class<?> clazz, final String methodName) throws SecurityException {
|
||||||
|
return getMethodByName(clazz, true, methodName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按照方法名查找指定方法名的方法,只返回匹配到的第一个方法,如果找不到对应的方法则返回{@code null}
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 此方法只检查方法名是否一致,并不检查参数的一致性。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param clazz 类,如果为{@code null}返回{@code null}
|
||||||
|
* @param ignoreCase 是否忽略大小写
|
||||||
|
* @param methodName 方法名,如果为空字符串返回{@code null}
|
||||||
|
* @return 方法
|
||||||
|
* @throws SecurityException 无权访问抛出异常
|
||||||
|
* @since 4.3.2
|
||||||
|
*/
|
||||||
|
public static Method getMethodByName(final Class<?> clazz, final boolean ignoreCase, final String methodName) throws SecurityException {
|
||||||
|
if (null == clazz || StrUtil.isBlank(methodName)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Method[] methods = getMethods(clazz);
|
||||||
|
if (ArrayUtil.isNotEmpty(methods)) {
|
||||||
|
for (final Method method : methods) {
|
||||||
|
if (StrUtil.equals(methodName, method.getName(), ignoreCase)
|
||||||
|
// 排除桥接方法
|
||||||
|
&& false == method.isBridge()) {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定类中的Public方法名<br>
|
||||||
|
* 去重重载的方法
|
||||||
|
*
|
||||||
|
* @param clazz 类
|
||||||
|
* @return 方法名Set
|
||||||
|
* @throws SecurityException 安全异常
|
||||||
|
*/
|
||||||
|
public static Set<String> getMethodNames(final Class<?> clazz) throws SecurityException {
|
||||||
|
final HashSet<String> methodSet = new HashSet<>();
|
||||||
|
final Method[] methods = getMethods(clazz);
|
||||||
|
for (final Method method : methods) {
|
||||||
|
methodSet.add(method.getName());
|
||||||
|
}
|
||||||
|
return methodSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定类过滤后的Public方法列表
|
||||||
|
*
|
||||||
|
* @param clazz 查找方法的类
|
||||||
|
* @param filter 过滤器
|
||||||
|
* @return 过滤后的方法列表
|
||||||
|
* @throws SecurityException 安全异常
|
||||||
|
*/
|
||||||
|
public static Method[] getMethods(final Class<?> clazz, final Filter<Method> filter) throws SecurityException {
|
||||||
|
if (null == clazz) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ArrayUtil.filter(getMethods(clazz), filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得一个类中所有方法列表,包括其父类中的方法
|
||||||
|
*
|
||||||
|
* @param beanClass 类,非{@code null}
|
||||||
|
* @return 方法列表
|
||||||
|
* @throws SecurityException 安全检查异常
|
||||||
|
*/
|
||||||
|
public static Method[] getMethods(final Class<?> beanClass) throws SecurityException {
|
||||||
|
Assert.notNull(beanClass);
|
||||||
|
return METHODS_CACHE.computeIfAbsent(beanClass,
|
||||||
|
() -> getMethodsDirectly(beanClass, true, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得一个类中所有方法列表,直接反射获取,无缓存<br>
|
||||||
|
* 接口获取方法和默认方法,获取的方法包括:
|
||||||
|
* <ul>
|
||||||
|
* <li>本类中的所有方法(包括static方法)</li>
|
||||||
|
* <li>父类中的所有方法(包括static方法)</li>
|
||||||
|
* <li>Object中(包括static方法)</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param beanClass 类或接口
|
||||||
|
* @param withSupers 是否包括父类或接口的方法列表
|
||||||
|
* @param withMethodFromObject 是否包括Object中的方法
|
||||||
|
* @return 方法列表
|
||||||
|
* @throws SecurityException 安全检查异常
|
||||||
|
*/
|
||||||
|
public static Method[] getMethodsDirectly(final Class<?> beanClass, final boolean withSupers, final boolean withMethodFromObject) throws SecurityException {
|
||||||
|
Assert.notNull(beanClass);
|
||||||
|
|
||||||
|
if (beanClass.isInterface()) {
|
||||||
|
// 对于接口,直接调用Class.getMethods方法获取所有方法,因为接口都是public方法
|
||||||
|
return withSupers ? beanClass.getMethods() : beanClass.getDeclaredMethods();
|
||||||
|
}
|
||||||
|
|
||||||
|
final UniqueKeySet<String, Method> result = new UniqueKeySet<>(true, MethodUtil::getUniqueKey);
|
||||||
|
Class<?> searchType = beanClass;
|
||||||
|
while (searchType != null) {
|
||||||
|
if (false == withMethodFromObject && Object.class == searchType) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result.addAllIfAbsent(Arrays.asList(searchType.getDeclaredMethods()));
|
||||||
|
result.addAllIfAbsent(getDefaultMethodsFromInterface(searchType));
|
||||||
|
|
||||||
|
|
||||||
|
searchType = (withSupers && false == searchType.isInterface()) ? searchType.getSuperclass() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toArray(new Method[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为equals方法
|
||||||
|
*
|
||||||
|
* @param method 方法
|
||||||
|
* @return 是否为equals方法
|
||||||
|
*/
|
||||||
|
public static boolean isEqualsMethod(final Method method) {
|
||||||
|
if (method == null ||
|
||||||
|
1 != method.getParameterCount() ||
|
||||||
|
false == "equals".equals(method.getName())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (method.getParameterTypes()[0] == Object.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为hashCode方法
|
||||||
|
*
|
||||||
|
* @param method 方法
|
||||||
|
* @return 是否为hashCode方法
|
||||||
|
*/
|
||||||
|
public static boolean isHashCodeMethod(final Method method) {
|
||||||
|
return method != null//
|
||||||
|
&& "hashCode".equals(method.getName())//
|
||||||
|
&& isEmptyParam(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为toString方法
|
||||||
|
*
|
||||||
|
* @param method 方法
|
||||||
|
* @return 是否为toString方法
|
||||||
|
*/
|
||||||
|
public static boolean isToStringMethod(final Method method) {
|
||||||
|
return method != null//
|
||||||
|
&& "toString".equals(method.getName())//
|
||||||
|
&& isEmptyParam(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为无参数方法
|
||||||
|
*
|
||||||
|
* @param method 方法
|
||||||
|
* @return 是否为无参数方法
|
||||||
|
* @since 5.1.1
|
||||||
|
*/
|
||||||
|
public static boolean isEmptyParam(final Method method) {
|
||||||
|
return method.getParameterCount() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查给定方法是否为Getter或者Setter方法,规则为:<br>
|
||||||
|
* <ul>
|
||||||
|
* <li>方法参数必须为0个或1个</li>
|
||||||
|
* <li>如果是无参方法,则判断是否以“get”或“is”开头</li>
|
||||||
|
* <li>如果方法参数1个,则判断是否以“set”开头</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param method 方法
|
||||||
|
* @return 是否为Getter或者Setter方法
|
||||||
|
* @since 5.7.20
|
||||||
|
*/
|
||||||
|
public static boolean isGetterOrSetterIgnoreCase(final Method method) {
|
||||||
|
return isGetterOrSetter(method, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查给定方法是否为Getter或者Setter方法,规则为:<br>
|
||||||
|
* <ul>
|
||||||
|
* <li>方法参数必须为0个或1个</li>
|
||||||
|
* <li>方法名称不能是getClass</li>
|
||||||
|
* <li>如果是无参方法,则判断是否以“get”或“is”开头</li>
|
||||||
|
* <li>如果方法参数1个,则判断是否以“set”开头</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param method 方法
|
||||||
|
* @param ignoreCase 是否忽略方法名的大小写
|
||||||
|
* @return 是否为Getter或者Setter方法
|
||||||
|
* @since 5.7.20
|
||||||
|
*/
|
||||||
|
public static boolean isGetterOrSetter(final Method method, final boolean ignoreCase) {
|
||||||
|
if (null == method) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 参数个数必须为0或1
|
||||||
|
final int parameterCount = method.getParameterCount();
|
||||||
|
if (parameterCount > 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String name = method.getName();
|
||||||
|
// 跳过getClass这个特殊方法
|
||||||
|
if ("getClass".equals(name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ignoreCase) {
|
||||||
|
name = name.toLowerCase();
|
||||||
|
}
|
||||||
|
switch (parameterCount) {
|
||||||
|
case 0:
|
||||||
|
return name.startsWith("get") || name.startsWith("is");
|
||||||
|
case 1:
|
||||||
|
return name.startsWith("set");
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------------------- invoke
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行静态方法
|
||||||
|
*
|
||||||
|
* @param <T> 对象类型
|
||||||
|
* @param method 方法(对象方法或static方法都可)
|
||||||
|
* @param args 参数对象
|
||||||
|
* @return 结果
|
||||||
|
* @throws UtilException 多种异常包装
|
||||||
|
*/
|
||||||
|
public static <T> T invokeStatic(final Method method, final Object... args) throws UtilException {
|
||||||
|
return invoke(null, method, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行方法<br>
|
||||||
|
* 执行前要检查给定参数:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* 1. 参数个数是否与方法参数个数一致
|
||||||
|
* 2. 如果某个参数为null但是方法这个位置的参数为原始类型,则赋予原始类型默认值
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <T> 返回对象类型
|
||||||
|
* @param obj 对象,如果执行静态方法,此值为{@code null}
|
||||||
|
* @param method 方法(对象方法或static方法都可)
|
||||||
|
* @param args 参数对象
|
||||||
|
* @return 结果
|
||||||
|
* @throws UtilException 一些列异常的包装
|
||||||
|
*/
|
||||||
|
public static <T> T invokeWithCheck(final Object obj, final Method method, final Object... args) throws UtilException {
|
||||||
|
final Class<?>[] types = method.getParameterTypes();
|
||||||
|
if (null != args) {
|
||||||
|
Assert.isTrue(args.length == types.length, "Params length [{}] is not fit for param length [{}] of method !", args.length, types.length);
|
||||||
|
Class<?> type;
|
||||||
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
type = types[i];
|
||||||
|
if (type.isPrimitive() && null == args[i]) {
|
||||||
|
// 参数是原始类型,而传入参数为null时赋予默认值
|
||||||
|
args[i] = ClassUtil.getDefaultValue(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return invoke(obj, method, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行方法
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 对于用户传入参数会做必要检查,包括:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* 1、忽略多余的参数
|
||||||
|
* 2、参数不够补齐默认值
|
||||||
|
* 3、传入参数为null,但是目标参数类型为原始类型,做转换
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <T> 返回对象类型
|
||||||
|
* @param obj 对象,如果执行静态方法,此值为{@code null}
|
||||||
|
* @param method 方法(对象方法或static方法都可)
|
||||||
|
* @param args 参数对象
|
||||||
|
* @return 结果
|
||||||
|
* @throws UtilException 一些列异常的包装
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> T invoke(final Object obj, final Method method, final Object... args) throws UtilException {
|
||||||
|
ReflectUtil.setAccessible(method);
|
||||||
|
|
||||||
|
// 检查用户传入参数:
|
||||||
|
// 1、忽略多余的参数
|
||||||
|
// 2、参数不够补齐默认值
|
||||||
|
// 3、通过NullWrapperBean传递的参数,会直接赋值null
|
||||||
|
// 4、传入参数为null,但是目标参数类型为原始类型,做转换
|
||||||
|
// 5、传入参数类型不对应,尝试转换类型
|
||||||
|
final Class<?>[] parameterTypes = method.getParameterTypes();
|
||||||
|
final Object[] actualArgs = new Object[parameterTypes.length];
|
||||||
|
if (null != args) {
|
||||||
|
for (int i = 0; i < actualArgs.length; i++) {
|
||||||
|
if (i >= args.length || null == args[i]) {
|
||||||
|
// 越界或者空值
|
||||||
|
actualArgs[i] = ClassUtil.getDefaultValue(parameterTypes[i]);
|
||||||
|
} else if (args[i] instanceof NullWrapperBean) {
|
||||||
|
//如果是通过NullWrapperBean传递的null参数,直接赋值null
|
||||||
|
actualArgs[i] = null;
|
||||||
|
} else if (false == parameterTypes[i].isAssignableFrom(args[i].getClass())) {
|
||||||
|
//对于类型不同的字段,尝试转换,转换失败则使用原对象类型
|
||||||
|
final Object targetValue = Convert.convert(parameterTypes[i], args[i]);
|
||||||
|
if (null != targetValue) {
|
||||||
|
actualArgs[i] = targetValue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
actualArgs[i] = args[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method.isDefault()) {
|
||||||
|
// 当方法是default方法时,尤其对象是代理对象,需使用句柄方式执行
|
||||||
|
// 代理对象情况下调用method.invoke会导致循环引用执行,最终栈溢出
|
||||||
|
return MethodHandleUtil.invokeSpecial(obj, method, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return (T) method.invoke(ModifierUtil.isStatic(method) ? null : obj, actualArgs);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
throw new UtilException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行对象中指定方法
|
||||||
|
* 如果需要传递的参数为null,请使用NullWrapperBean来传递,不然会丢失类型信息
|
||||||
|
*
|
||||||
|
* @param <T> 返回对象类型
|
||||||
|
* @param obj 方法所在对象
|
||||||
|
* @param methodName 方法名
|
||||||
|
* @param args 参数列表
|
||||||
|
* @return 执行结果
|
||||||
|
* @throws UtilException IllegalAccessException包装
|
||||||
|
* @see NullWrapperBean
|
||||||
|
* @since 3.1.2
|
||||||
|
*/
|
||||||
|
public static <T> T invoke(final Object obj, final String methodName, final Object... args) throws UtilException {
|
||||||
|
Assert.notNull(obj, "Object to get method must be not null!");
|
||||||
|
Assert.notBlank(methodName, "Method name must be not blank!");
|
||||||
|
|
||||||
|
final Method method = getMethodOfObj(obj, methodName, args);
|
||||||
|
if (null == method) {
|
||||||
|
throw new UtilException("No such method: [{}] from [{}]", methodName, obj.getClass());
|
||||||
|
}
|
||||||
|
return invoke(obj, method, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行方法<br>
|
||||||
|
* 可执行Private方法,也可执行static方法<br>
|
||||||
|
* 执行非static方法时,必须满足对象有默认构造方法<br>
|
||||||
|
* 非单例模式,如果是非静态方法,每次创建一个新对象
|
||||||
|
*
|
||||||
|
* @param <T> 对象类型
|
||||||
|
* @param classNameWithMethodName 类名和方法名表达式,类名与方法名用{@code .}或{@code #}连接 例如:com.xiaoleilu.hutool.StrUtil.isEmpty 或 com.xiaoleilu.hutool.StrUtil#isEmpty
|
||||||
|
* @param args 参数,必须严格对应指定方法的参数类型和数量
|
||||||
|
* @return 返回结果
|
||||||
|
*/
|
||||||
|
public static <T> T invoke(final String classNameWithMethodName, final Object[] args) {
|
||||||
|
return invoke(classNameWithMethodName, false, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行方法<br>
|
||||||
|
* 可执行Private方法,也可执行static方法<br>
|
||||||
|
* 执行非static方法时,必须满足对象有默认构造方法<br>
|
||||||
|
*
|
||||||
|
* @param <T> 对象类型
|
||||||
|
* @param classNameWithMethodName 类名和方法名表达式,例如:com.xiaoleilu.hutool.StrUtil#isEmpty或com.xiaoleilu.hutool.StrUtil.isEmpty
|
||||||
|
* @param isSingleton 是否为单例对象,如果此参数为false,每次执行方法时创建一个新对象
|
||||||
|
* @param args 参数,必须严格对应指定方法的参数类型和数量
|
||||||
|
* @return 返回结果
|
||||||
|
*/
|
||||||
|
public static <T> T invoke(final String classNameWithMethodName, final boolean isSingleton, final Object... args) {
|
||||||
|
if (StrUtil.isBlank(classNameWithMethodName)) {
|
||||||
|
throw new UtilException("Blank classNameDotMethodName!");
|
||||||
|
}
|
||||||
|
|
||||||
|
int splitIndex = classNameWithMethodName.lastIndexOf('#');
|
||||||
|
if (splitIndex <= 0) {
|
||||||
|
splitIndex = classNameWithMethodName.lastIndexOf('.');
|
||||||
|
}
|
||||||
|
if (splitIndex <= 0) {
|
||||||
|
throw new UtilException("Invalid classNameWithMethodName [{}]!", classNameWithMethodName);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String className = classNameWithMethodName.substring(0, splitIndex);
|
||||||
|
final String methodName = classNameWithMethodName.substring(splitIndex + 1);
|
||||||
|
|
||||||
|
return invoke(className, methodName, isSingleton, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行方法<br>
|
||||||
|
* 可执行Private方法,也可执行static方法<br>
|
||||||
|
* 执行非static方法时,必须满足对象有默认构造方法<br>
|
||||||
|
* 非单例模式,如果是非静态方法,每次创建一个新对象
|
||||||
|
*
|
||||||
|
* @param <T> 对象类型
|
||||||
|
* @param className 类名,完整类路径
|
||||||
|
* @param methodName 方法名
|
||||||
|
* @param args 参数,必须严格对应指定方法的参数类型和数量
|
||||||
|
* @return 返回结果
|
||||||
|
*/
|
||||||
|
public static <T> T invoke(final String className, final String methodName, final Object[] args) {
|
||||||
|
return invoke(className, methodName, false, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行方法<br>
|
||||||
|
* 可执行Private方法,也可执行static方法<br>
|
||||||
|
* 执行非static方法时,必须满足对象有默认构造方法<br>
|
||||||
|
*
|
||||||
|
* @param <T> 对象类型
|
||||||
|
* @param className 类名,完整类路径
|
||||||
|
* @param methodName 方法名
|
||||||
|
* @param isSingleton 是否为单例对象,如果此参数为false,每次执行方法时创建一个新对象
|
||||||
|
* @param args 参数,必须严格对应指定方法的参数类型和数量
|
||||||
|
* @return 返回结果
|
||||||
|
*/
|
||||||
|
public static <T> T invoke(final String className, final String methodName, final boolean isSingleton, final Object... args) {
|
||||||
|
final Class<?> clazz = ClassLoaderUtil.loadClass(className);
|
||||||
|
try {
|
||||||
|
final Method method = MethodUtil.getMethod(clazz, methodName, ClassUtil.getClasses(args));
|
||||||
|
if (null == method) {
|
||||||
|
throw new NoSuchMethodException(StrUtil.format("No such method: [{}]", methodName));
|
||||||
|
}
|
||||||
|
if (ModifierUtil.isStatic(method)) {
|
||||||
|
return MethodUtil.invoke(null, method, args);
|
||||||
|
} else {
|
||||||
|
return MethodUtil.invoke(isSingleton ? Singleton.get(clazz) : clazz.newInstance(), method, args);
|
||||||
|
}
|
||||||
|
} catch (final Exception e) {
|
||||||
|
throw new UtilException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取方法的唯一键,结构为:
|
||||||
|
* <pre>
|
||||||
|
* 返回类型#方法名:参数1类型,参数2类型...
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param method 方法
|
||||||
|
* @return 方法唯一键
|
||||||
|
*/
|
||||||
|
private static String getUniqueKey(final Method method) {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(method.getReturnType().getName()).append('#');
|
||||||
|
sb.append(method.getName());
|
||||||
|
final Class<?>[] parameters = method.getParameterTypes();
|
||||||
|
for (int i = 0; i < parameters.length; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
sb.append(':');
|
||||||
|
} else {
|
||||||
|
sb.append(',');
|
||||||
|
}
|
||||||
|
sb.append(parameters[i].getName());
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取类对应接口中的非抽象方法(default方法)
|
||||||
|
*
|
||||||
|
* @param clazz 类
|
||||||
|
* @return 方法列表
|
||||||
|
*/
|
||||||
|
private static List<Method> getDefaultMethodsFromInterface(final Class<?> clazz) {
|
||||||
|
final List<Method> result = new ArrayList<>();
|
||||||
|
for (final Class<?> ifc : clazz.getInterfaces()) {
|
||||||
|
for (final Method m : ifc.getMethods()) {
|
||||||
|
if (false == ModifierUtil.isAbstract(m)) {
|
||||||
|
result.add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,6 @@
|
|||||||
package cn.hutool.core.reflect;
|
package cn.hutool.core.reflect;
|
||||||
|
|
||||||
import cn.hutool.core.annotation.Alias;
|
import cn.hutool.core.annotation.Alias;
|
||||||
import cn.hutool.core.bean.NullWrapperBean;
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import cn.hutool.core.collection.UniqueKeySet;
|
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.exceptions.UtilException;
|
import cn.hutool.core.exceptions.UtilException;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
@ -17,10 +14,8 @@ import java.lang.reflect.AccessibleObject;
|
|||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.AbstractMap;
|
import java.util.AbstractMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -43,11 +38,6 @@ public class ReflectUtil {
|
|||||||
* 字段缓存
|
* 字段缓存
|
||||||
*/
|
*/
|
||||||
private static final WeakConcurrentMap<Class<?>, Field[]> FIELDS_CACHE = new WeakConcurrentMap<>();
|
private static final WeakConcurrentMap<Class<?>, Field[]> FIELDS_CACHE = new WeakConcurrentMap<>();
|
||||||
/**
|
|
||||||
* 方法缓存
|
|
||||||
*/
|
|
||||||
private static final WeakConcurrentMap<Class<?>, Method[]> METHODS_CACHE = new WeakConcurrentMap<>();
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------------------- Constructor
|
// --------------------------------------------------------------------------------------------------------- Constructor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -374,442 +364,6 @@ public class ReflectUtil {
|
|||||||
return "this$0".equals(field.getName());
|
return "this$0".equals(field.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------------------- method
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得指定类本类及其父类中的Public方法名<br>
|
|
||||||
* 去重重载的方法
|
|
||||||
*
|
|
||||||
* @param clazz 类
|
|
||||||
* @return 方法名Set
|
|
||||||
*/
|
|
||||||
public static Set<String> getPublicMethodNames(final Class<?> clazz) {
|
|
||||||
final HashSet<String> methodSet = new HashSet<>();
|
|
||||||
final Method[] methodArray = getPublicMethods(clazz);
|
|
||||||
if (ArrayUtil.isNotEmpty(methodArray)) {
|
|
||||||
for (final Method method : methodArray) {
|
|
||||||
methodSet.add(method.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return methodSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得本类及其父类所有Public方法
|
|
||||||
*
|
|
||||||
* @param clazz 查找方法的类
|
|
||||||
* @return 过滤后的方法列表
|
|
||||||
*/
|
|
||||||
public static Method[] getPublicMethods(final Class<?> clazz) {
|
|
||||||
return null == clazz ? null : clazz.getMethods();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得指定类过滤后的Public方法列表<br>
|
|
||||||
*
|
|
||||||
* @param clazz 查找方法的类
|
|
||||||
* @param filter 过滤器
|
|
||||||
* @return 过滤后的方法数组
|
|
||||||
*/
|
|
||||||
public static Method[] getPublicMethods(final Class<?> clazz, final Filter<Method> filter) {
|
|
||||||
if (null == clazz) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Method[] methods = getPublicMethods(clazz);
|
|
||||||
if(null == filter){
|
|
||||||
return methods;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ArrayUtil.filter(methods, filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得指定类过滤后的Public方法列表
|
|
||||||
*
|
|
||||||
* @param clazz 查找方法的类
|
|
||||||
* @param excludeMethods 不包括的方法
|
|
||||||
* @return 过滤后的方法列表
|
|
||||||
*/
|
|
||||||
public static Method[] getPublicMethods(final Class<?> clazz, final Method... excludeMethods) {
|
|
||||||
final HashSet<Method> excludeMethodSet = CollUtil.newHashSet(excludeMethods);
|
|
||||||
return getPublicMethods(clazz, method -> false == excludeMethodSet.contains(method));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得指定类过滤后的Public方法列表
|
|
||||||
*
|
|
||||||
* @param clazz 查找方法的类
|
|
||||||
* @param excludeMethodNames 不包括的方法名列表
|
|
||||||
* @return 过滤后的方法数组
|
|
||||||
*/
|
|
||||||
public static Method[] getPublicMethods(final Class<?> clazz, final String... excludeMethodNames) {
|
|
||||||
final HashSet<String> excludeMethodNameSet = CollUtil.newHashSet(excludeMethodNames);
|
|
||||||
return getPublicMethods(clazz, method -> false == excludeMethodNameSet.contains(method.getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查找指定Public方法 如果找不到对应的方法或方法不为public的则返回{@code null}
|
|
||||||
*
|
|
||||||
* @param clazz 类
|
|
||||||
* @param methodName 方法名
|
|
||||||
* @param paramTypes 参数类型
|
|
||||||
* @return 方法
|
|
||||||
* @throws SecurityException 无权访问抛出异常
|
|
||||||
*/
|
|
||||||
public static Method getPublicMethod(final Class<?> clazz, final String methodName, final Class<?>... paramTypes) throws SecurityException {
|
|
||||||
try {
|
|
||||||
return clazz.getMethod(methodName, paramTypes);
|
|
||||||
} catch (final NoSuchMethodException ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查找指定对象中的所有方法(包括非public方法),也包括父对象和Object类的方法
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 此方法为精准获取方法名,即方法名和参数数量和类型必须一致,否则返回{@code null}。
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param obj 被查找的对象,如果为{@code null}返回{@code null}
|
|
||||||
* @param methodName 方法名,如果为空字符串返回{@code null}
|
|
||||||
* @param args 参数
|
|
||||||
* @return 方法
|
|
||||||
* @throws SecurityException 无访问权限抛出异常
|
|
||||||
*/
|
|
||||||
public static Method getMethodOfObj(final Object obj, final String methodName, final Object... args) throws SecurityException {
|
|
||||||
if (null == obj || StrUtil.isBlank(methodName)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return getMethod(obj.getClass(), methodName, ClassUtil.getClasses(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 忽略大小写查找指定方法,如果找不到对应的方法则返回{@code null}
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 此方法为精准获取方法名,即方法名和参数数量和类型必须一致,否则返回{@code null}。
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param clazz 类,如果为{@code null}返回{@code null}
|
|
||||||
* @param methodName 方法名,如果为空字符串返回{@code null}
|
|
||||||
* @param paramTypes 参数类型,指定参数类型如果是方法的子类也算
|
|
||||||
* @return 方法
|
|
||||||
* @throws SecurityException 无权访问抛出异常
|
|
||||||
* @since 3.2.0
|
|
||||||
*/
|
|
||||||
public static Method getMethodIgnoreCase(final Class<?> clazz, final String methodName, final Class<?>... paramTypes) throws SecurityException {
|
|
||||||
return getMethod(clazz, true, methodName, paramTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查找指定方法 如果找不到对应的方法则返回{@code null}
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 此方法为精准获取方法名,即方法名和参数数量和类型必须一致,否则返回{@code null}。
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param clazz 类,如果为{@code null}返回{@code null}
|
|
||||||
* @param methodName 方法名,如果为空字符串返回{@code null}
|
|
||||||
* @param paramTypes 参数类型,指定参数类型如果是方法的子类也算
|
|
||||||
* @return 方法
|
|
||||||
* @throws SecurityException 无权访问抛出异常
|
|
||||||
*/
|
|
||||||
public static Method getMethod(final Class<?> clazz, final String methodName, final Class<?>... paramTypes) throws SecurityException {
|
|
||||||
return getMethod(clazz, false, methodName, paramTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查找指定方法 如果找不到对应的方法则返回{@code null}<br>
|
|
||||||
* 此方法为精准获取方法名,即方法名和参数数量和类型必须一致,否则返回{@code null}。<br>
|
|
||||||
* 如果查找的方法有多个同参数类型重载,查找第一个找到的方法
|
|
||||||
*
|
|
||||||
* @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(final Class<?> clazz, final boolean ignoreCase, final String methodName, final Class<?>... paramTypes) throws SecurityException {
|
|
||||||
if (null == clazz || StrUtil.isBlank(methodName)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Method[] methods = getMethods(clazz);
|
|
||||||
if (ArrayUtil.isNotEmpty(methods)) {
|
|
||||||
for (final Method method : methods) {
|
|
||||||
if (StrUtil.equals(methodName, method.getName(), ignoreCase)
|
|
||||||
&& ClassUtil.isAllAssignableFrom(method.getParameterTypes(), paramTypes)
|
|
||||||
//排除桥接方法,pr#1965@Github
|
|
||||||
&& false == method.isBridge()) {
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 按照方法名查找指定方法名的方法,只返回匹配到的第一个方法,如果找不到对应的方法则返回{@code null}
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 此方法只检查方法名是否一致,并不检查参数的一致性。
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param clazz 类,如果为{@code null}返回{@code null}
|
|
||||||
* @param methodName 方法名,如果为空字符串返回{@code null}
|
|
||||||
* @return 方法
|
|
||||||
* @throws SecurityException 无权访问抛出异常
|
|
||||||
* @since 4.3.2
|
|
||||||
*/
|
|
||||||
public static Method getMethodByName(final Class<?> clazz, final String methodName) throws SecurityException {
|
|
||||||
return getMethodByName(clazz, false, methodName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 按照方法名查找指定方法名的方法,只返回匹配到的第一个方法,如果找不到对应的方法则返回{@code null}
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 此方法只检查方法名是否一致(忽略大小写),并不检查参数的一致性。
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param clazz 类,如果为{@code null}返回{@code null}
|
|
||||||
* @param methodName 方法名,如果为空字符串返回{@code null}
|
|
||||||
* @return 方法
|
|
||||||
* @throws SecurityException 无权访问抛出异常
|
|
||||||
* @since 4.3.2
|
|
||||||
*/
|
|
||||||
public static Method getMethodByNameIgnoreCase(final Class<?> clazz, final String methodName) throws SecurityException {
|
|
||||||
return getMethodByName(clazz, true, methodName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 按照方法名查找指定方法名的方法,只返回匹配到的第一个方法,如果找不到对应的方法则返回{@code null}
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 此方法只检查方法名是否一致,并不检查参数的一致性。
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param clazz 类,如果为{@code null}返回{@code null}
|
|
||||||
* @param ignoreCase 是否忽略大小写
|
|
||||||
* @param methodName 方法名,如果为空字符串返回{@code null}
|
|
||||||
* @return 方法
|
|
||||||
* @throws SecurityException 无权访问抛出异常
|
|
||||||
* @since 4.3.2
|
|
||||||
*/
|
|
||||||
public static Method getMethodByName(final Class<?> clazz, final boolean ignoreCase, final String methodName) throws SecurityException {
|
|
||||||
if (null == clazz || StrUtil.isBlank(methodName)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Method[] methods = getMethods(clazz);
|
|
||||||
if (ArrayUtil.isNotEmpty(methods)) {
|
|
||||||
for (final Method method : methods) {
|
|
||||||
if (StrUtil.equals(methodName, method.getName(), ignoreCase)
|
|
||||||
// 排除桥接方法
|
|
||||||
&& false == method.isBridge()) {
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得指定类中的Public方法名<br>
|
|
||||||
* 去重重载的方法
|
|
||||||
*
|
|
||||||
* @param clazz 类
|
|
||||||
* @return 方法名Set
|
|
||||||
* @throws SecurityException 安全异常
|
|
||||||
*/
|
|
||||||
public static Set<String> getMethodNames(final Class<?> clazz) throws SecurityException {
|
|
||||||
final HashSet<String> methodSet = new HashSet<>();
|
|
||||||
final Method[] methods = getMethods(clazz);
|
|
||||||
for (final Method method : methods) {
|
|
||||||
methodSet.add(method.getName());
|
|
||||||
}
|
|
||||||
return methodSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得指定类过滤后的Public方法列表
|
|
||||||
*
|
|
||||||
* @param clazz 查找方法的类
|
|
||||||
* @param filter 过滤器
|
|
||||||
* @return 过滤后的方法列表
|
|
||||||
* @throws SecurityException 安全异常
|
|
||||||
*/
|
|
||||||
public static Method[] getMethods(final Class<?> clazz, final Filter<Method> filter) throws SecurityException {
|
|
||||||
if (null == clazz) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return ArrayUtil.filter(getMethods(clazz), filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得一个类中所有方法列表,包括其父类中的方法
|
|
||||||
*
|
|
||||||
* @param beanClass 类,非{@code null}
|
|
||||||
* @return 方法列表
|
|
||||||
* @throws SecurityException 安全检查异常
|
|
||||||
*/
|
|
||||||
public static Method[] getMethods(final Class<?> beanClass) throws SecurityException {
|
|
||||||
Assert.notNull(beanClass);
|
|
||||||
return METHODS_CACHE.computeIfAbsent(beanClass,
|
|
||||||
() -> getMethodsDirectly(beanClass, true, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得一个类中所有方法列表,直接反射获取,无缓存<br>
|
|
||||||
* 接口获取方法和默认方法,获取的方法包括:
|
|
||||||
* <ul>
|
|
||||||
* <li>本类中的所有方法(包括static方法)</li>
|
|
||||||
* <li>父类中的所有方法(包括static方法)</li>
|
|
||||||
* <li>Object中(包括static方法)</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param beanClass 类或接口
|
|
||||||
* @param withSupers 是否包括父类或接口的方法列表
|
|
||||||
* @param withMethodFromObject 是否包括Object中的方法
|
|
||||||
* @return 方法列表
|
|
||||||
* @throws SecurityException 安全检查异常
|
|
||||||
*/
|
|
||||||
public static Method[] getMethodsDirectly(final Class<?> beanClass, final boolean withSupers, final boolean withMethodFromObject) throws SecurityException {
|
|
||||||
Assert.notNull(beanClass);
|
|
||||||
|
|
||||||
if (beanClass.isInterface()) {
|
|
||||||
// 对于接口,直接调用Class.getMethods方法获取所有方法,因为接口都是public方法
|
|
||||||
return withSupers ? beanClass.getMethods() : beanClass.getDeclaredMethods();
|
|
||||||
}
|
|
||||||
|
|
||||||
final UniqueKeySet<String, Method> result = new UniqueKeySet<>(true, ReflectUtil::getUniqueKey);
|
|
||||||
Class<?> searchType = beanClass;
|
|
||||||
while (searchType != null) {
|
|
||||||
if (false == withMethodFromObject && Object.class == searchType) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
result.addAllIfAbsent(Arrays.asList(searchType.getDeclaredMethods()));
|
|
||||||
result.addAllIfAbsent(getDefaultMethodsFromInterface(searchType));
|
|
||||||
|
|
||||||
|
|
||||||
searchType = (withSupers && false == searchType.isInterface()) ? searchType.getSuperclass() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.toArray(new Method[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否为equals方法
|
|
||||||
*
|
|
||||||
* @param method 方法
|
|
||||||
* @return 是否为equals方法
|
|
||||||
*/
|
|
||||||
public static boolean isEqualsMethod(final Method method) {
|
|
||||||
if (method == null ||
|
|
||||||
1 != method.getParameterCount() ||
|
|
||||||
false == "equals".equals(method.getName())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return (method.getParameterTypes()[0] == Object.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否为hashCode方法
|
|
||||||
*
|
|
||||||
* @param method 方法
|
|
||||||
* @return 是否为hashCode方法
|
|
||||||
*/
|
|
||||||
public static boolean isHashCodeMethod(final Method method) {
|
|
||||||
return method != null//
|
|
||||||
&& "hashCode".equals(method.getName())//
|
|
||||||
&& isEmptyParam(method);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否为toString方法
|
|
||||||
*
|
|
||||||
* @param method 方法
|
|
||||||
* @return 是否为toString方法
|
|
||||||
*/
|
|
||||||
public static boolean isToStringMethod(final Method method) {
|
|
||||||
return method != null//
|
|
||||||
&& "toString".equals(method.getName())//
|
|
||||||
&& isEmptyParam(method);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否为无参数方法
|
|
||||||
*
|
|
||||||
* @param method 方法
|
|
||||||
* @return 是否为无参数方法
|
|
||||||
* @since 5.1.1
|
|
||||||
*/
|
|
||||||
public static boolean isEmptyParam(final Method method) {
|
|
||||||
return method.getParameterCount() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查给定方法是否为Getter或者Setter方法,规则为:<br>
|
|
||||||
* <ul>
|
|
||||||
* <li>方法参数必须为0个或1个</li>
|
|
||||||
* <li>如果是无参方法,则判断是否以“get”或“is”开头</li>
|
|
||||||
* <li>如果方法参数1个,则判断是否以“set”开头</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param method 方法
|
|
||||||
* @return 是否为Getter或者Setter方法
|
|
||||||
* @since 5.7.20
|
|
||||||
*/
|
|
||||||
public static boolean isGetterOrSetterIgnoreCase(final Method method) {
|
|
||||||
return isGetterOrSetter(method, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查给定方法是否为Getter或者Setter方法,规则为:<br>
|
|
||||||
* <ul>
|
|
||||||
* <li>方法参数必须为0个或1个</li>
|
|
||||||
* <li>方法名称不能是getClass</li>
|
|
||||||
* <li>如果是无参方法,则判断是否以“get”或“is”开头</li>
|
|
||||||
* <li>如果方法参数1个,则判断是否以“set”开头</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param method 方法
|
|
||||||
* @param ignoreCase 是否忽略方法名的大小写
|
|
||||||
* @return 是否为Getter或者Setter方法
|
|
||||||
* @since 5.7.20
|
|
||||||
*/
|
|
||||||
public static boolean isGetterOrSetter(final Method method, final boolean ignoreCase) {
|
|
||||||
if (null == method) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 参数个数必须为0或1
|
|
||||||
final int parameterCount = method.getParameterCount();
|
|
||||||
if (parameterCount > 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String name = method.getName();
|
|
||||||
// 跳过getClass这个特殊方法
|
|
||||||
if ("getClass".equals(name)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (ignoreCase) {
|
|
||||||
name = name.toLowerCase();
|
|
||||||
}
|
|
||||||
switch (parameterCount) {
|
|
||||||
case 0:
|
|
||||||
return name.startsWith("get") || name.startsWith("is");
|
|
||||||
case 1:
|
|
||||||
return name.startsWith("set");
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// --------------------------------------------------------------------------------------------------------- newInstance
|
// --------------------------------------------------------------------------------------------------------- newInstance
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -927,142 +481,6 @@ public class ReflectUtil {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------------------- invoke
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行静态方法
|
|
||||||
*
|
|
||||||
* @param <T> 对象类型
|
|
||||||
* @param method 方法(对象方法或static方法都可)
|
|
||||||
* @param args 参数对象
|
|
||||||
* @return 结果
|
|
||||||
* @throws UtilException 多种异常包装
|
|
||||||
*/
|
|
||||||
public static <T> T invokeStatic(final Method method, final Object... args) throws UtilException {
|
|
||||||
return invoke(null, method, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行方法<br>
|
|
||||||
* 执行前要检查给定参数:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* 1. 参数个数是否与方法参数个数一致
|
|
||||||
* 2. 如果某个参数为null但是方法这个位置的参数为原始类型,则赋予原始类型默认值
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <T> 返回对象类型
|
|
||||||
* @param obj 对象,如果执行静态方法,此值为{@code null}
|
|
||||||
* @param method 方法(对象方法或static方法都可)
|
|
||||||
* @param args 参数对象
|
|
||||||
* @return 结果
|
|
||||||
* @throws UtilException 一些列异常的包装
|
|
||||||
*/
|
|
||||||
public static <T> T invokeWithCheck(final Object obj, final Method method, final Object... args) throws UtilException {
|
|
||||||
final Class<?>[] types = method.getParameterTypes();
|
|
||||||
if (null != args) {
|
|
||||||
Assert.isTrue(args.length == types.length, "Params length [{}] is not fit for param length [{}] of method !", args.length, types.length);
|
|
||||||
Class<?> type;
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
|
||||||
type = types[i];
|
|
||||||
if (type.isPrimitive() && null == args[i]) {
|
|
||||||
// 参数是原始类型,而传入参数为null时赋予默认值
|
|
||||||
args[i] = ClassUtil.getDefaultValue(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return invoke(obj, method, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行方法
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 对于用户传入参数会做必要检查,包括:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* 1、忽略多余的参数
|
|
||||||
* 2、参数不够补齐默认值
|
|
||||||
* 3、传入参数为null,但是目标参数类型为原始类型,做转换
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <T> 返回对象类型
|
|
||||||
* @param obj 对象,如果执行静态方法,此值为{@code null}
|
|
||||||
* @param method 方法(对象方法或static方法都可)
|
|
||||||
* @param args 参数对象
|
|
||||||
* @return 结果
|
|
||||||
* @throws UtilException 一些列异常的包装
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static <T> T invoke(final Object obj, final Method method, final Object... args) throws UtilException {
|
|
||||||
setAccessible(method);
|
|
||||||
|
|
||||||
// 检查用户传入参数:
|
|
||||||
// 1、忽略多余的参数
|
|
||||||
// 2、参数不够补齐默认值
|
|
||||||
// 3、通过NullWrapperBean传递的参数,会直接赋值null
|
|
||||||
// 4、传入参数为null,但是目标参数类型为原始类型,做转换
|
|
||||||
// 5、传入参数类型不对应,尝试转换类型
|
|
||||||
final Class<?>[] parameterTypes = method.getParameterTypes();
|
|
||||||
final Object[] actualArgs = new Object[parameterTypes.length];
|
|
||||||
if (null != args) {
|
|
||||||
for (int i = 0; i < actualArgs.length; i++) {
|
|
||||||
if (i >= args.length || null == args[i]) {
|
|
||||||
// 越界或者空值
|
|
||||||
actualArgs[i] = ClassUtil.getDefaultValue(parameterTypes[i]);
|
|
||||||
} else if (args[i] instanceof NullWrapperBean) {
|
|
||||||
//如果是通过NullWrapperBean传递的null参数,直接赋值null
|
|
||||||
actualArgs[i] = null;
|
|
||||||
} else if (false == parameterTypes[i].isAssignableFrom(args[i].getClass())) {
|
|
||||||
//对于类型不同的字段,尝试转换,转换失败则使用原对象类型
|
|
||||||
final Object targetValue = Convert.convert(parameterTypes[i], args[i]);
|
|
||||||
if (null != targetValue) {
|
|
||||||
actualArgs[i] = targetValue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
actualArgs[i] = args[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method.isDefault()) {
|
|
||||||
// 当方法是default方法时,尤其对象是代理对象,需使用句柄方式执行
|
|
||||||
// 代理对象情况下调用method.invoke会导致循环引用执行,最终栈溢出
|
|
||||||
return MethodHandleUtil.invokeSpecial(obj, method, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return (T) method.invoke(ClassUtil.isStatic(method) ? null : obj, actualArgs);
|
|
||||||
} catch (final Exception e) {
|
|
||||||
throw new UtilException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行对象中指定方法
|
|
||||||
* 如果需要传递的参数为null,请使用NullWrapperBean来传递,不然会丢失类型信息
|
|
||||||
*
|
|
||||||
* @param <T> 返回对象类型
|
|
||||||
* @param obj 方法所在对象
|
|
||||||
* @param methodName 方法名
|
|
||||||
* @param args 参数列表
|
|
||||||
* @return 执行结果
|
|
||||||
* @throws UtilException IllegalAccessException包装
|
|
||||||
* @see NullWrapperBean
|
|
||||||
* @since 3.1.2
|
|
||||||
*/
|
|
||||||
public static <T> T invoke(final Object obj, final String methodName, final Object... args) throws UtilException {
|
|
||||||
Assert.notNull(obj, "Object to get method must be not null!");
|
|
||||||
Assert.notBlank(methodName, "Method name must be not blank!");
|
|
||||||
|
|
||||||
final Method method = getMethodOfObj(obj, methodName, args);
|
|
||||||
if (null == method) {
|
|
||||||
throw new UtilException("No such method: [{}] from [{}]", methodName, obj.getClass());
|
|
||||||
}
|
|
||||||
return invoke(obj, method, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置方法为可访问(私有方法可以被外部调用)
|
* 设置方法为可访问(私有方法可以被外部调用)
|
||||||
*
|
*
|
||||||
@ -1077,47 +495,4 @@ public class ReflectUtil {
|
|||||||
}
|
}
|
||||||
return accessibleObject;
|
return accessibleObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取方法的唯一键,结构为:
|
|
||||||
* <pre>
|
|
||||||
* 返回类型#方法名:参数1类型,参数2类型...
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param method 方法
|
|
||||||
* @return 方法唯一键
|
|
||||||
*/
|
|
||||||
private static String getUniqueKey(final Method method) {
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append(method.getReturnType().getName()).append('#');
|
|
||||||
sb.append(method.getName());
|
|
||||||
final Class<?>[] parameters = method.getParameterTypes();
|
|
||||||
for (int i = 0; i < parameters.length; i++) {
|
|
||||||
if (i == 0) {
|
|
||||||
sb.append(':');
|
|
||||||
} else {
|
|
||||||
sb.append(',');
|
|
||||||
}
|
|
||||||
sb.append(parameters[i].getName());
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取类对应接口中的非抽象方法(default方法)
|
|
||||||
*
|
|
||||||
* @param clazz 类
|
|
||||||
* @return 方法列表
|
|
||||||
*/
|
|
||||||
private static List<Method> getDefaultMethodsFromInterface(final Class<?> clazz) {
|
|
||||||
final List<Method> result = new ArrayList<>();
|
|
||||||
for (final Class<?> ifc : clazz.getInterfaces()) {
|
|
||||||
for (final Method m : ifc.getMethods()) {
|
|
||||||
if (false == ModifierUtil.isAbstract(m)) {
|
|
||||||
result.add(m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,9 @@ import cn.hutool.core.lang.func.Func1;
|
|||||||
import cn.hutool.core.lang.mutable.Mutable;
|
import cn.hutool.core.lang.mutable.Mutable;
|
||||||
import cn.hutool.core.lang.mutable.MutableObj;
|
import cn.hutool.core.lang.mutable.MutableObj;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.util.ObjUtil;
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
|
||||||
import cn.hutool.core.text.StrUtil;
|
import cn.hutool.core.text.StrUtil;
|
||||||
|
import cn.hutool.core.util.ObjUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -244,7 +244,7 @@ public class ReUtil {
|
|||||||
final Map<String, String> result = MapUtil.newHashMap(m.groupCount());
|
final Map<String, String> result = MapUtil.newHashMap(m.groupCount());
|
||||||
if (m.find()) {
|
if (m.find()) {
|
||||||
// 通过反射获取 namedGroups 方法
|
// 通过反射获取 namedGroups 方法
|
||||||
final Map<String, Integer> map = ReflectUtil.invoke(pattern, "namedGroups");
|
final Map<String, Integer> map = MethodUtil.invoke(pattern, "namedGroups");
|
||||||
map.forEach((key, value) -> result.put(key, m.group(value)));
|
map.forEach((key, value) -> result.put(key, m.group(value)));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -5,10 +5,10 @@ import cn.hutool.core.comparator.CompareUtil;
|
|||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.exceptions.UtilException;
|
import cn.hutool.core.exceptions.UtilException;
|
||||||
import cn.hutool.core.io.SerializeUtil;
|
import cn.hutool.core.io.SerializeUtil;
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.math.NumberUtil;
|
import cn.hutool.core.math.NumberUtil;
|
||||||
import cn.hutool.core.reflect.ClassUtil;
|
import cn.hutool.core.reflect.ClassUtil;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.map.MapUtil;
|
|
||||||
import cn.hutool.core.text.StrUtil;
|
import cn.hutool.core.text.StrUtil;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
@ -441,7 +441,7 @@ public class ObjUtil {
|
|||||||
T result = ArrayUtil.clone(obj);
|
T result = ArrayUtil.clone(obj);
|
||||||
if (null == result) {
|
if (null == result) {
|
||||||
if (obj instanceof Cloneable) {
|
if (obj instanceof Cloneable) {
|
||||||
result = ReflectUtil.invoke(obj, "clone");
|
result = MethodUtil.invoke(obj, "clone");
|
||||||
} else {
|
} else {
|
||||||
result = cloneByStream(obj);
|
result = cloneByStream(obj);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package cn.hutool.core.reflect;
|
package cn.hutool.core.reflect;
|
||||||
|
|
||||||
import cn.hutool.core.reflect.MethodHandleUtil;
|
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
|
||||||
import cn.hutool.core.classloader.ClassLoaderUtil;
|
import cn.hutool.core.classloader.ClassLoaderUtil;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -23,12 +21,12 @@ public class MethodHandleUtilTest {
|
|||||||
Assert.assertEquals("Quack", duck.quack());
|
Assert.assertEquals("Quack", duck.quack());
|
||||||
|
|
||||||
// 测试子类执行default方法
|
// 测试子类执行default方法
|
||||||
final Method quackMethod = ReflectUtil.getMethod(Duck.class, "quack");
|
final Method quackMethod = MethodUtil.getMethod(Duck.class, "quack");
|
||||||
String quack = MethodHandleUtil.invokeSpecial(new BigDuck(), quackMethod);
|
String quack = MethodHandleUtil.invokeSpecial(new BigDuck(), quackMethod);
|
||||||
Assert.assertEquals("Quack", quack);
|
Assert.assertEquals("Quack", quack);
|
||||||
|
|
||||||
// 测试反射执行默认方法
|
// 测试反射执行默认方法
|
||||||
quack = ReflectUtil.invoke(new Duck() {}, quackMethod);
|
quack = MethodUtil.invoke(new Duck() {}, quackMethod);
|
||||||
Assert.assertEquals("Quack", quack);
|
Assert.assertEquals("Quack", quack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +35,7 @@ public class MethodHandleUtilTest {
|
|||||||
final Duck duck = (Duck) Proxy.newProxyInstance(
|
final Duck duck = (Duck) Proxy.newProxyInstance(
|
||||||
ClassLoaderUtil.getClassLoader(),
|
ClassLoaderUtil.getClassLoader(),
|
||||||
new Class[] { Duck.class },
|
new Class[] { Duck.class },
|
||||||
ReflectUtil::invoke);
|
MethodUtil::invoke);
|
||||||
|
|
||||||
Assert.assertEquals("Quack", duck.quack());
|
Assert.assertEquals("Quack", duck.quack());
|
||||||
}
|
}
|
||||||
@ -47,7 +45,7 @@ public class MethodHandleUtilTest {
|
|||||||
final Duck duck = (Duck) Proxy.newProxyInstance(
|
final Duck duck = (Duck) Proxy.newProxyInstance(
|
||||||
ClassLoaderUtil.getClassLoader(),
|
ClassLoaderUtil.getClassLoader(),
|
||||||
new Class[] { Duck.class },
|
new Class[] { Duck.class },
|
||||||
ReflectUtil::invoke);
|
MethodUtil::invoke);
|
||||||
|
|
||||||
Assert.assertEquals("Quack", duck.quack());
|
Assert.assertEquals("Quack", duck.quack());
|
||||||
}
|
}
|
||||||
@ -56,7 +54,7 @@ public class MethodHandleUtilTest {
|
|||||||
public void invokeTest(){
|
public void invokeTest(){
|
||||||
// 测试执行普通方法
|
// 测试执行普通方法
|
||||||
final int size = MethodHandleUtil.invokeSpecial(new BigDuck(),
|
final int size = MethodHandleUtil.invokeSpecial(new BigDuck(),
|
||||||
ReflectUtil.getMethod(BigDuck.class, "getSize"));
|
MethodUtil.getMethod(BigDuck.class, "getSize"));
|
||||||
Assert.assertEquals(36, size);
|
Assert.assertEquals(36, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +62,7 @@ public class MethodHandleUtilTest {
|
|||||||
public void invokeStaticTest(){
|
public void invokeStaticTest(){
|
||||||
// 测试执行普通方法
|
// 测试执行普通方法
|
||||||
final String result = MethodHandleUtil.invoke(null,
|
final String result = MethodHandleUtil.invoke(null,
|
||||||
ReflectUtil.getMethod(Duck.class, "getDuck", int.class), 78);
|
MethodUtil.getMethod(Duck.class, "getDuck", int.class), 78);
|
||||||
Assert.assertEquals("Duck 78", result);
|
Assert.assertEquals("Duck 78", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,169 @@
|
|||||||
|
package cn.hutool.core.reflect;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.date.TimeInterval;
|
||||||
|
import cn.hutool.core.lang.Console;
|
||||||
|
import cn.hutool.core.lang.test.bean.ExamInfoDict;
|
||||||
|
import cn.hutool.core.text.StrUtil;
|
||||||
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
public class MethodUtilTest {
|
||||||
|
@Test
|
||||||
|
public void getMethodsTest() {
|
||||||
|
Method[] methods = MethodUtil.getMethods(ExamInfoDict.class);
|
||||||
|
Assert.assertEquals(20, methods.length);
|
||||||
|
|
||||||
|
//过滤器测试
|
||||||
|
methods = MethodUtil.getMethods(ExamInfoDict.class, t -> Integer.class.equals(t.getReturnType()));
|
||||||
|
|
||||||
|
Assert.assertEquals(4, methods.length);
|
||||||
|
final Method method = methods[0];
|
||||||
|
Assert.assertNotNull(method);
|
||||||
|
|
||||||
|
//null过滤器测试
|
||||||
|
methods = MethodUtil.getMethods(ExamInfoDict.class, null);
|
||||||
|
|
||||||
|
Assert.assertEquals(20, methods.length);
|
||||||
|
final Method method2 = methods[0];
|
||||||
|
Assert.assertNotNull(method2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getMethodTest() {
|
||||||
|
Method method = MethodUtil.getMethod(ExamInfoDict.class, "getId");
|
||||||
|
Assert.assertEquals("getId", method.getName());
|
||||||
|
Assert.assertEquals(0, method.getParameterTypes().length);
|
||||||
|
|
||||||
|
method = MethodUtil.getMethod(ExamInfoDict.class, "getId", Integer.class);
|
||||||
|
Assert.assertEquals("getId", method.getName());
|
||||||
|
Assert.assertEquals(1, method.getParameterTypes().length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getMethodIgnoreCaseTest() {
|
||||||
|
Method method = MethodUtil.getMethodIgnoreCase(ExamInfoDict.class, "getId");
|
||||||
|
Assert.assertEquals("getId", method.getName());
|
||||||
|
Assert.assertEquals(0, method.getParameterTypes().length);
|
||||||
|
|
||||||
|
method = MethodUtil.getMethodIgnoreCase(ExamInfoDict.class, "GetId");
|
||||||
|
Assert.assertEquals("getId", method.getName());
|
||||||
|
Assert.assertEquals(0, method.getParameterTypes().length);
|
||||||
|
|
||||||
|
method = MethodUtil.getMethodIgnoreCase(ExamInfoDict.class, "setanswerIs", Integer.class);
|
||||||
|
Assert.assertEquals("setAnswerIs", method.getName());
|
||||||
|
Assert.assertEquals(1, method.getParameterTypes().length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void invokeTest() {
|
||||||
|
final ReflectUtilTest.AClass testClass = new ReflectUtilTest.AClass();
|
||||||
|
MethodUtil.invoke(testClass, "setA", 10);
|
||||||
|
Assert.assertEquals(10, testClass.getA());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void getMethodBenchTest() {
|
||||||
|
// 预热
|
||||||
|
getMethodWithReturnTypeCheck(ReflectUtilTest.TestBenchClass.class, false, "getH");
|
||||||
|
|
||||||
|
final TimeInterval timer = DateUtil.timer();
|
||||||
|
timer.start();
|
||||||
|
for (int i = 0; i < 100000000; i++) {
|
||||||
|
MethodUtil.getMethod(ReflectUtilTest.TestBenchClass.class, false, "getH");
|
||||||
|
}
|
||||||
|
Console.log(timer.interval());
|
||||||
|
|
||||||
|
timer.restart();
|
||||||
|
for (int i = 0; i < 100000000; i++) {
|
||||||
|
getMethodWithReturnTypeCheck(ReflectUtilTest.TestBenchClass.class, false, "getH");
|
||||||
|
}
|
||||||
|
Console.log(timer.interval());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Method getMethodWithReturnTypeCheck(final Class<?> clazz, final boolean ignoreCase, final String methodName, final Class<?>... paramTypes) throws SecurityException {
|
||||||
|
if (null == clazz || StrUtil.isBlank(methodName)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Method res = null;
|
||||||
|
final Method[] methods = MethodUtil.getMethods(clazz);
|
||||||
|
if (ArrayUtil.isNotEmpty(methods)) {
|
||||||
|
for (final Method method : methods) {
|
||||||
|
if (StrUtil.equals(methodName, method.getName(), ignoreCase)
|
||||||
|
&& ClassUtil.isAllAssignableFrom(method.getParameterTypes(), paramTypes)
|
||||||
|
&& (res == null
|
||||||
|
|| res.getReturnType().isAssignableFrom(method.getReturnType()))) {
|
||||||
|
res = method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getMethodsFromClassExtends() {
|
||||||
|
// 继承情况下,需解决方法去重问题
|
||||||
|
Method[] methods = MethodUtil.getMethods(ReflectUtilTest.C2.class);
|
||||||
|
Assert.assertEquals(15, methods.length);
|
||||||
|
|
||||||
|
// 排除Object中的方法
|
||||||
|
// 3个方法包括类
|
||||||
|
methods = MethodUtil.getMethodsDirectly(ReflectUtilTest.C2.class, true, false);
|
||||||
|
Assert.assertEquals(3, methods.length);
|
||||||
|
|
||||||
|
// getA属于本类
|
||||||
|
Assert.assertEquals("public void cn.hutool.core.reflect.ReflectUtilTest$C2.getA()", methods[0].toString());
|
||||||
|
// getB属于父类
|
||||||
|
Assert.assertEquals("public void cn.hutool.core.reflect.ReflectUtilTest$C1.getB()", methods[1].toString());
|
||||||
|
// getC属于接口中的默认方法
|
||||||
|
Assert.assertEquals("public default void cn.hutool.core.reflect.ReflectUtilTest$TestInterface1.getC()", methods[2].toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getMethodsFromInterfaceTest() {
|
||||||
|
// 对于接口,直接调用Class.getMethods方法获取所有方法,因为接口都是public方法
|
||||||
|
// 因此此处得到包括TestInterface1、TestInterface2、TestInterface3中一共4个方法
|
||||||
|
final Method[] methods = MethodUtil.getMethods(ReflectUtilTest.TestInterface3.class);
|
||||||
|
Assert.assertEquals(4, methods.length);
|
||||||
|
|
||||||
|
// 接口里,调用getMethods和getPublicMethods效果相同
|
||||||
|
final Method[] publicMethods = MethodUtil.getPublicMethods(ReflectUtilTest.TestInterface3.class);
|
||||||
|
Assert.assertArrayEquals(methods, publicMethods);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getPublicMethod() {
|
||||||
|
final Method superPublicMethod = MethodUtil.getPublicMethod(ReflectUtilTest.TestSubClass.class, "publicMethod");
|
||||||
|
Assert.assertNotNull(superPublicMethod);
|
||||||
|
final Method superPrivateMethod = MethodUtil.getPublicMethod(ReflectUtilTest.TestSubClass.class, "privateMethod");
|
||||||
|
Assert.assertNull(superPrivateMethod);
|
||||||
|
|
||||||
|
final Method publicMethod = MethodUtil.getPublicMethod(ReflectUtilTest.TestSubClass.class, "publicSubMethod");
|
||||||
|
Assert.assertNotNull(publicMethod);
|
||||||
|
final Method privateMethod = MethodUtil.getPublicMethod(ReflectUtilTest.TestSubClass.class, "privateSubMethod");
|
||||||
|
Assert.assertNull(privateMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDeclaredMethod() {
|
||||||
|
final Method noMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "noMethod");
|
||||||
|
Assert.assertNull(noMethod);
|
||||||
|
|
||||||
|
final Method privateMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "privateMethod");
|
||||||
|
Assert.assertNotNull(privateMethod);
|
||||||
|
final Method publicMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "publicMethod");
|
||||||
|
Assert.assertNotNull(publicMethod);
|
||||||
|
|
||||||
|
final Method publicSubMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "publicSubMethod");
|
||||||
|
Assert.assertNotNull(publicSubMethod);
|
||||||
|
final Method privateSubMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "privateSubMethod");
|
||||||
|
Assert.assertNotNull(privateSubMethod);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,178 @@
|
|||||||
|
package cn.hutool.core.reflect;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.Week;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反射工具类单元测试
|
||||||
|
*
|
||||||
|
* @author Looly
|
||||||
|
*/
|
||||||
|
public class ReflectUtilTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFieldTest() {
|
||||||
|
// 能够获取到父类字段
|
||||||
|
final Field privateField = ReflectUtil.getField(TestSubClass.class, "privateField");
|
||||||
|
Assert.assertNotNull(privateField);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFieldsTest() {
|
||||||
|
// 能够获取到父类字段
|
||||||
|
final Field[] fields = ReflectUtil.getFields(TestSubClass.class);
|
||||||
|
Assert.assertEquals(4, fields.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setFieldTest() {
|
||||||
|
final AClass testClass = new AClass();
|
||||||
|
ReflectUtil.setFieldValue(testClass, "a", "111");
|
||||||
|
Assert.assertEquals(111, testClass.getA());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void noneStaticInnerClassTest() {
|
||||||
|
final NoneStaticClass testAClass = ReflectUtil.newInstanceIfPossible(NoneStaticClass.class);
|
||||||
|
Assert.assertNotNull(testAClass);
|
||||||
|
Assert.assertEquals(2, testAClass.getA());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static class AClass {
|
||||||
|
private int a;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@SuppressWarnings("InnerClassMayBeStatic")
|
||||||
|
class NoneStaticClass {
|
||||||
|
private int a = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static class TestBenchClass {
|
||||||
|
private int a;
|
||||||
|
private String b;
|
||||||
|
private String c;
|
||||||
|
private String d;
|
||||||
|
private String e;
|
||||||
|
private String f;
|
||||||
|
private String g;
|
||||||
|
private String h;
|
||||||
|
private String i;
|
||||||
|
private String j;
|
||||||
|
private String k;
|
||||||
|
private String l;
|
||||||
|
private String m;
|
||||||
|
private String n;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TestInterface1 {
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
void getA();
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
void getB();
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
default void getC() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("AbstractMethodOverridesAbstractMethod")
|
||||||
|
interface TestInterface2 extends TestInterface1 {
|
||||||
|
@Override
|
||||||
|
void getB();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TestInterface3 extends TestInterface2 {
|
||||||
|
void get3();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("InnerClassMayBeStatic")
|
||||||
|
class C1 implements TestInterface2 {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getA() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getB() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class C2 extends C1 {
|
||||||
|
@Override
|
||||||
|
public void getA() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void newInstanceIfPossibleTest(){
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
final int intValue = ReflectUtil.newInstanceIfPossible(int.class);
|
||||||
|
Assert.assertEquals(0, intValue);
|
||||||
|
|
||||||
|
final Integer integer = ReflectUtil.newInstanceIfPossible(Integer.class);
|
||||||
|
Assert.assertEquals(new Integer(0), integer);
|
||||||
|
|
||||||
|
final Map<?, ?> map = ReflectUtil.newInstanceIfPossible(Map.class);
|
||||||
|
Assert.assertNotNull(map);
|
||||||
|
|
||||||
|
final Collection<?> collection = ReflectUtil.newInstanceIfPossible(Collection.class);
|
||||||
|
Assert.assertNotNull(collection);
|
||||||
|
|
||||||
|
final Week week = ReflectUtil.newInstanceIfPossible(Week.class);
|
||||||
|
Assert.assertEquals(Week.SUNDAY, week);
|
||||||
|
|
||||||
|
final int[] intArray = ReflectUtil.newInstanceIfPossible(int[].class);
|
||||||
|
Assert.assertArrayEquals(new int[0], intArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDeclaredField() {
|
||||||
|
final Field noField = ReflectUtil.getField(TestSubClass.class, "noField");
|
||||||
|
Assert.assertNull(noField);
|
||||||
|
|
||||||
|
// 获取不到父类字段
|
||||||
|
final Field field = ReflectUtil.getDeClearField(TestSubClass.class, "field");
|
||||||
|
Assert.assertNull(field);
|
||||||
|
|
||||||
|
final Field subField = ReflectUtil.getField(TestSubClass.class, "subField");
|
||||||
|
Assert.assertNotNull(subField);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
static class TestClass {
|
||||||
|
private String privateField;
|
||||||
|
protected String field;
|
||||||
|
|
||||||
|
private void privateMethod() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void publicMethod() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"InnerClassMayBeStatic", "unused"})
|
||||||
|
class TestSubClass extends TestClass {
|
||||||
|
private String subField;
|
||||||
|
|
||||||
|
private void privateSubMethod() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void publicSubMethod() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,341 +0,0 @@
|
|||||||
package cn.hutool.core.util;
|
|
||||||
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
|
||||||
import cn.hutool.core.date.TimeInterval;
|
|
||||||
import cn.hutool.core.date.Week;
|
|
||||||
import cn.hutool.core.lang.Console;
|
|
||||||
import cn.hutool.core.lang.test.bean.ExamInfoDict;
|
|
||||||
import cn.hutool.core.reflect.ClassUtil;
|
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
|
||||||
import cn.hutool.core.text.StrUtil;
|
|
||||||
import lombok.Data;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 反射工具类单元测试
|
|
||||||
*
|
|
||||||
* @author Looly
|
|
||||||
*/
|
|
||||||
public class ReflectUtilTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getMethodsTest() {
|
|
||||||
Method[] methods = ReflectUtil.getMethods(ExamInfoDict.class);
|
|
||||||
Assert.assertEquals(20, methods.length);
|
|
||||||
|
|
||||||
//过滤器测试
|
|
||||||
methods = ReflectUtil.getMethods(ExamInfoDict.class, t -> Integer.class.equals(t.getReturnType()));
|
|
||||||
|
|
||||||
Assert.assertEquals(4, methods.length);
|
|
||||||
final Method method = methods[0];
|
|
||||||
Assert.assertNotNull(method);
|
|
||||||
|
|
||||||
//null过滤器测试
|
|
||||||
methods = ReflectUtil.getMethods(ExamInfoDict.class, null);
|
|
||||||
|
|
||||||
Assert.assertEquals(20, methods.length);
|
|
||||||
final Method method2 = methods[0];
|
|
||||||
Assert.assertNotNull(method2);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getMethodTest() {
|
|
||||||
Method method = ReflectUtil.getMethod(ExamInfoDict.class, "getId");
|
|
||||||
Assert.assertEquals("getId", method.getName());
|
|
||||||
Assert.assertEquals(0, method.getParameterTypes().length);
|
|
||||||
|
|
||||||
method = ReflectUtil.getMethod(ExamInfoDict.class, "getId", Integer.class);
|
|
||||||
Assert.assertEquals("getId", method.getName());
|
|
||||||
Assert.assertEquals(1, method.getParameterTypes().length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getMethodIgnoreCaseTest() {
|
|
||||||
Method method = ReflectUtil.getMethodIgnoreCase(ExamInfoDict.class, "getId");
|
|
||||||
Assert.assertEquals("getId", method.getName());
|
|
||||||
Assert.assertEquals(0, method.getParameterTypes().length);
|
|
||||||
|
|
||||||
method = ReflectUtil.getMethodIgnoreCase(ExamInfoDict.class, "GetId");
|
|
||||||
Assert.assertEquals("getId", method.getName());
|
|
||||||
Assert.assertEquals(0, method.getParameterTypes().length);
|
|
||||||
|
|
||||||
method = ReflectUtil.getMethodIgnoreCase(ExamInfoDict.class, "setanswerIs", Integer.class);
|
|
||||||
Assert.assertEquals("setAnswerIs", method.getName());
|
|
||||||
Assert.assertEquals(1, method.getParameterTypes().length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getFieldTest() {
|
|
||||||
// 能够获取到父类字段
|
|
||||||
final Field privateField = ReflectUtil.getField(TestSubClass.class, "privateField");
|
|
||||||
Assert.assertNotNull(privateField);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getFieldsTest() {
|
|
||||||
// 能够获取到父类字段
|
|
||||||
final Field[] fields = ReflectUtil.getFields(TestSubClass.class);
|
|
||||||
Assert.assertEquals(4, fields.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void setFieldTest() {
|
|
||||||
final AClass testClass = new AClass();
|
|
||||||
ReflectUtil.setFieldValue(testClass, "a", "111");
|
|
||||||
Assert.assertEquals(111, testClass.getA());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeTest() {
|
|
||||||
final AClass testClass = new AClass();
|
|
||||||
ReflectUtil.invoke(testClass, "setA", 10);
|
|
||||||
Assert.assertEquals(10, testClass.getA());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void noneStaticInnerClassTest() {
|
|
||||||
final NoneStaticClass testAClass = ReflectUtil.newInstanceIfPossible(NoneStaticClass.class);
|
|
||||||
Assert.assertNotNull(testAClass);
|
|
||||||
Assert.assertEquals(2, testAClass.getA());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
static class AClass {
|
|
||||||
private int a;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@SuppressWarnings("InnerClassMayBeStatic")
|
|
||||||
class NoneStaticClass {
|
|
||||||
private int a = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Ignore
|
|
||||||
public void getMethodBenchTest() {
|
|
||||||
// 预热
|
|
||||||
getMethodWithReturnTypeCheck(TestBenchClass.class, false, "getH");
|
|
||||||
|
|
||||||
final TimeInterval timer = DateUtil.timer();
|
|
||||||
timer.start();
|
|
||||||
for (int i = 0; i < 100000000; i++) {
|
|
||||||
ReflectUtil.getMethod(TestBenchClass.class, false, "getH");
|
|
||||||
}
|
|
||||||
Console.log(timer.interval());
|
|
||||||
|
|
||||||
timer.restart();
|
|
||||||
for (int i = 0; i < 100000000; i++) {
|
|
||||||
getMethodWithReturnTypeCheck(TestBenchClass.class, false, "getH");
|
|
||||||
}
|
|
||||||
Console.log(timer.interval());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
static class TestBenchClass {
|
|
||||||
private int a;
|
|
||||||
private String b;
|
|
||||||
private String c;
|
|
||||||
private String d;
|
|
||||||
private String e;
|
|
||||||
private String f;
|
|
||||||
private String g;
|
|
||||||
private String h;
|
|
||||||
private String i;
|
|
||||||
private String j;
|
|
||||||
private String k;
|
|
||||||
private String l;
|
|
||||||
private String m;
|
|
||||||
private String n;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Method getMethodWithReturnTypeCheck(final Class<?> clazz, final boolean ignoreCase, final String methodName, final Class<?>... paramTypes) throws SecurityException {
|
|
||||||
if (null == clazz || StrUtil.isBlank(methodName)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Method res = null;
|
|
||||||
final Method[] methods = ReflectUtil.getMethods(clazz);
|
|
||||||
if (ArrayUtil.isNotEmpty(methods)) {
|
|
||||||
for (final Method method : methods) {
|
|
||||||
if (StrUtil.equals(methodName, method.getName(), ignoreCase)
|
|
||||||
&& ClassUtil.isAllAssignableFrom(method.getParameterTypes(), paramTypes)
|
|
||||||
&& (res == null
|
|
||||||
|| res.getReturnType().isAssignableFrom(method.getReturnType()))) {
|
|
||||||
res = method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getMethodsFromClassExtends() {
|
|
||||||
// 继承情况下,需解决方法去重问题
|
|
||||||
Method[] methods = ReflectUtil.getMethods(C2.class);
|
|
||||||
Assert.assertEquals(15, methods.length);
|
|
||||||
|
|
||||||
// 排除Object中的方法
|
|
||||||
// 3个方法包括类
|
|
||||||
methods = ReflectUtil.getMethodsDirectly(C2.class, true, false);
|
|
||||||
Assert.assertEquals(3, methods.length);
|
|
||||||
|
|
||||||
// getA属于本类
|
|
||||||
Assert.assertEquals("public void cn.hutool.core.util.ReflectUtilTest$C2.getA()", methods[0].toString());
|
|
||||||
// getB属于父类
|
|
||||||
Assert.assertEquals("public void cn.hutool.core.util.ReflectUtilTest$C1.getB()", methods[1].toString());
|
|
||||||
// getC属于接口中的默认方法
|
|
||||||
Assert.assertEquals("public default void cn.hutool.core.util.ReflectUtilTest$TestInterface1.getC()", methods[2].toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getMethodsFromInterfaceTest() {
|
|
||||||
// 对于接口,直接调用Class.getMethods方法获取所有方法,因为接口都是public方法
|
|
||||||
// 因此此处得到包括TestInterface1、TestInterface2、TestInterface3中一共4个方法
|
|
||||||
final Method[] methods = ReflectUtil.getMethods(TestInterface3.class);
|
|
||||||
Assert.assertEquals(4, methods.length);
|
|
||||||
|
|
||||||
// 接口里,调用getMethods和getPublicMethods效果相同
|
|
||||||
final Method[] publicMethods = ReflectUtil.getPublicMethods(TestInterface3.class);
|
|
||||||
Assert.assertArrayEquals(methods, publicMethods);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TestInterface1 {
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
void getA();
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
void getB();
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
default void getC() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("AbstractMethodOverridesAbstractMethod")
|
|
||||||
interface TestInterface2 extends TestInterface1 {
|
|
||||||
@Override
|
|
||||||
void getB();
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TestInterface3 extends TestInterface2 {
|
|
||||||
void get3();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("InnerClassMayBeStatic")
|
|
||||||
class C1 implements TestInterface2 {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getA() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getB() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class C2 extends C1 {
|
|
||||||
@Override
|
|
||||||
public void getA() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void newInstanceIfPossibleTest(){
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
final int intValue = ReflectUtil.newInstanceIfPossible(int.class);
|
|
||||||
Assert.assertEquals(0, intValue);
|
|
||||||
|
|
||||||
final Integer integer = ReflectUtil.newInstanceIfPossible(Integer.class);
|
|
||||||
Assert.assertEquals(new Integer(0), integer);
|
|
||||||
|
|
||||||
final Map<?, ?> map = ReflectUtil.newInstanceIfPossible(Map.class);
|
|
||||||
Assert.assertNotNull(map);
|
|
||||||
|
|
||||||
final Collection<?> collection = ReflectUtil.newInstanceIfPossible(Collection.class);
|
|
||||||
Assert.assertNotNull(collection);
|
|
||||||
|
|
||||||
final Week week = ReflectUtil.newInstanceIfPossible(Week.class);
|
|
||||||
Assert.assertEquals(Week.SUNDAY, week);
|
|
||||||
|
|
||||||
final int[] intArray = ReflectUtil.newInstanceIfPossible(int[].class);
|
|
||||||
Assert.assertArrayEquals(new int[0], intArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getPublicMethod() {
|
|
||||||
final Method superPublicMethod = ReflectUtil.getPublicMethod(TestSubClass.class, "publicMethod");
|
|
||||||
Assert.assertNotNull(superPublicMethod);
|
|
||||||
final Method superPrivateMethod = ReflectUtil.getPublicMethod(TestSubClass.class, "privateMethod");
|
|
||||||
Assert.assertNull(superPrivateMethod);
|
|
||||||
|
|
||||||
final Method publicMethod = ReflectUtil.getPublicMethod(TestSubClass.class, "publicSubMethod");
|
|
||||||
Assert.assertNotNull(publicMethod);
|
|
||||||
final Method privateMethod = ReflectUtil.getPublicMethod(TestSubClass.class, "privateSubMethod");
|
|
||||||
Assert.assertNull(privateMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getDeclaredMethod() {
|
|
||||||
final Method noMethod = ReflectUtil.getMethod(TestSubClass.class, "noMethod");
|
|
||||||
Assert.assertNull(noMethod);
|
|
||||||
|
|
||||||
final Method privateMethod = ReflectUtil.getMethod(TestSubClass.class, "privateMethod");
|
|
||||||
Assert.assertNotNull(privateMethod);
|
|
||||||
final Method publicMethod = ReflectUtil.getMethod(TestSubClass.class, "publicMethod");
|
|
||||||
Assert.assertNotNull(publicMethod);
|
|
||||||
|
|
||||||
final Method publicSubMethod = ReflectUtil.getMethod(TestSubClass.class, "publicSubMethod");
|
|
||||||
Assert.assertNotNull(publicSubMethod);
|
|
||||||
final Method privateSubMethod = ReflectUtil.getMethod(TestSubClass.class, "privateSubMethod");
|
|
||||||
Assert.assertNotNull(privateSubMethod);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getDeclaredField() {
|
|
||||||
final Field noField = ReflectUtil.getField(TestSubClass.class, "noField");
|
|
||||||
Assert.assertNull(noField);
|
|
||||||
|
|
||||||
// 获取不到父类字段
|
|
||||||
final Field field = ReflectUtil.getDeClearField(TestSubClass.class, "field");
|
|
||||||
Assert.assertNull(field);
|
|
||||||
|
|
||||||
final Field subField = ReflectUtil.getField(TestSubClass.class, "subField");
|
|
||||||
Assert.assertNotNull(subField);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
static class TestClass {
|
|
||||||
private String privateField;
|
|
||||||
protected String field;
|
|
||||||
|
|
||||||
private void privateMethod() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publicMethod() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({"InnerClassMayBeStatic", "unused"})
|
|
||||||
class TestSubClass extends TestClass {
|
|
||||||
private String subField;
|
|
||||||
|
|
||||||
private void privateSubMethod() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publicSubMethod() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
package cn.hutool.core.util;
|
package cn.hutool.core.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.reflect.ReflectUtil;
|
||||||
import cn.hutool.core.reflect.TypeUtil;
|
import cn.hutool.core.reflect.TypeUtil;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@ -15,7 +16,7 @@ public class TypeUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getEleTypeTest() {
|
public void getEleTypeTest() {
|
||||||
final Method method = ReflectUtil.getMethod(TestClass.class, "getList");
|
final Method method = MethodUtil.getMethod(TestClass.class, "getList");
|
||||||
final Type type = TypeUtil.getReturnType(method);
|
final Type type = TypeUtil.getReturnType(method);
|
||||||
Assert.assertEquals("java.util.List<java.lang.String>", type.toString());
|
Assert.assertEquals("java.util.List<java.lang.String>", type.toString());
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ public class TypeUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getParamTypeTest() {
|
public void getParamTypeTest() {
|
||||||
final Method method = ReflectUtil.getMethod(TestClass.class, "intTest", Integer.class);
|
final Method method = MethodUtil.getMethod(TestClass.class, "intTest", Integer.class);
|
||||||
final Type type = TypeUtil.getParamType(method, 0);
|
final Type type = TypeUtil.getParamType(method, 0);
|
||||||
Assert.assertEquals(Integer.class, type);
|
Assert.assertEquals(Integer.class, type);
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package cn.hutool.cron.task;
|
|||||||
|
|
||||||
import cn.hutool.core.classloader.ClassLoaderUtil;
|
import cn.hutool.core.classloader.ClassLoaderUtil;
|
||||||
import cn.hutool.core.exceptions.UtilException;
|
import cn.hutool.core.exceptions.UtilException;
|
||||||
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.reflect.ReflectUtil;
|
||||||
import cn.hutool.core.text.StrUtil;
|
import cn.hutool.core.text.StrUtil;
|
||||||
import cn.hutool.cron.CronException;
|
import cn.hutool.cron.CronException;
|
||||||
@ -50,7 +51,7 @@ public class InvokeTask implements Task{
|
|||||||
if(StrUtil.isBlank(methodName)) {
|
if(StrUtil.isBlank(methodName)) {
|
||||||
throw new IllegalArgumentException("Method name is blank !");
|
throw new IllegalArgumentException("Method name is blank !");
|
||||||
}
|
}
|
||||||
this.method = ReflectUtil.getPublicMethod(clazz, methodName);
|
this.method = MethodUtil.getPublicMethod(clazz, methodName);
|
||||||
if(null == this.method) {
|
if(null == this.method) {
|
||||||
throw new IllegalArgumentException("No method with name of [" + methodName + "] !");
|
throw new IllegalArgumentException("No method with name of [" + methodName + "] !");
|
||||||
}
|
}
|
||||||
@ -59,7 +60,7 @@ public class InvokeTask implements Task{
|
|||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void execute() {
|
||||||
try {
|
try {
|
||||||
ReflectUtil.invoke(this.obj, this.method);
|
MethodUtil.invoke(this.obj, this.method);
|
||||||
} catch (final UtilException e) {
|
} catch (final UtilException e) {
|
||||||
throw new CronException(e.getCause());
|
throw new CronException(e.getCause());
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package cn.hutool.db;
|
|||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.lang.func.Func0;
|
import cn.hutool.core.lang.func.Func0;
|
||||||
import cn.hutool.core.map.Dict;
|
import cn.hutool.core.map.Dict;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.text.StrUtil;
|
import cn.hutool.core.text.StrUtil;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.util.CharsetUtil;
|
import cn.hutool.core.util.CharsetUtil;
|
||||||
@ -301,7 +301,7 @@ public class Entity extends Dict {
|
|||||||
result = (Time) obj;
|
result = (Time) obj;
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
// try oracle.sql.TIMESTAMP
|
// try oracle.sql.TIMESTAMP
|
||||||
result = ReflectUtil.invoke(obj, "timeValue");
|
result = MethodUtil.invoke(obj, "timeValue");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -316,7 +316,7 @@ public class Entity extends Dict {
|
|||||||
result = (Date) obj;
|
result = (Date) obj;
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
// try oracle.sql.TIMESTAMP
|
// try oracle.sql.TIMESTAMP
|
||||||
result = ReflectUtil.invoke(obj, "dateValue");
|
result = MethodUtil.invoke(obj, "dateValue");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -331,7 +331,7 @@ public class Entity extends Dict {
|
|||||||
result = (Timestamp) obj;
|
result = (Timestamp) obj;
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
// try oracle.sql.TIMESTAMP
|
// try oracle.sql.TIMESTAMP
|
||||||
result = ReflectUtil.invoke(obj, "timestampValue");
|
result = MethodUtil.invoke(obj, "timestampValue");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
|
|||||||
import cn.hutool.core.bean.PropDesc;
|
import cn.hutool.core.bean.PropDesc;
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.reflect.ReflectUtil;
|
||||||
import cn.hutool.core.text.StrUtil;
|
import cn.hutool.core.text.StrUtil;
|
||||||
@ -100,7 +101,7 @@ public class ResultSetUtil {
|
|||||||
setter = (null == pd) ? null : pd.getSetter();
|
setter = (null == pd) ? null : pd.getSetter();
|
||||||
if (null != setter) {
|
if (null != setter) {
|
||||||
value = getColumnValue(rs, i, meta.getColumnType(i), TypeUtil.getFirstParamType(setter));
|
value = getColumnValue(rs, i, meta.getColumnType(i), TypeUtil.getFirstParamType(setter));
|
||||||
ReflectUtil.invokeWithCheck(bean, setter, value);
|
MethodUtil.invokeWithCheck(bean, setter, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bean;
|
return bean;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package cn.hutool.extra.aop.interceptor;
|
package cn.hutool.extra.aop.interceptor;
|
||||||
|
|
||||||
import cn.hutool.extra.aop.aspects.Aspect;
|
import cn.hutool.core.reflect.ModifierUtil;
|
||||||
import cn.hutool.core.reflect.ClassUtil;
|
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
import cn.hutool.core.reflect.ReflectUtil;
|
||||||
|
import cn.hutool.extra.aop.aspects.Aspect;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
@ -47,7 +47,7 @@ public class JdkInterceptor implements InvocationHandler, Serializable {
|
|||||||
ReflectUtil.setAccessible(method);
|
ReflectUtil.setAccessible(method);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = method.invoke(ClassUtil.isStatic(method) ? null : target, args);
|
result = method.invoke(ModifierUtil.isStatic(method) ? null : target, args);
|
||||||
} catch (final InvocationTargetException e) {
|
} catch (final InvocationTargetException e) {
|
||||||
// 异常回调(只捕获业务代码导致的异常,而非反射导致的异常)
|
// 异常回调(只捕获业务代码导致的异常,而非反射导致的异常)
|
||||||
if (aspect.afterException(target, method, args, e.getTargetException())) {
|
if (aspect.afterException(target, method, args, e.getTargetException())) {
|
||||||
|
@ -2,9 +2,9 @@ package cn.hutool.poi.excel.sax;
|
|||||||
|
|
||||||
import cn.hutool.core.io.IORuntimeException;
|
import cn.hutool.core.io.IORuntimeException;
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
import cn.hutool.core.util.ObjUtil;
|
import cn.hutool.core.reflect.MethodUtil;
|
||||||
import cn.hutool.core.reflect.ReflectUtil;
|
|
||||||
import cn.hutool.core.text.StrUtil;
|
import cn.hutool.core.text.StrUtil;
|
||||||
|
import cn.hutool.core.util.ObjUtil;
|
||||||
import cn.hutool.poi.excel.sax.handler.RowHandler;
|
import cn.hutool.poi.excel.sax.handler.RowHandler;
|
||||||
import cn.hutool.poi.exceptions.POIException;
|
import cn.hutool.poi.exceptions.POIException;
|
||||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||||
@ -20,7 +20,7 @@ import java.util.Iterator;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sax方式读取Excel文件<br>
|
* Sax方式读取Excel文件<br>
|
||||||
* Excel2007格式说明见:http://www.cnblogs.com/wangmingshun/p/6654143.html
|
* Excel2007格式说明见:<a href="http://www.cnblogs.com/wangmingshun/p/6654143.html">http://www.cnblogs.com/wangmingshun/p/6654143.html</a>
|
||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
* @since 3.1.2
|
* @since 3.1.2
|
||||||
@ -130,7 +130,7 @@ public class Excel07SaxReader implements ExcelSaxReader<Excel07SaxReader> {
|
|||||||
// 获取共享字符串表
|
// 获取共享字符串表
|
||||||
// POI-5.2.0开始返回值有所变更,导致实际使用时提示方法未找到,此处使用反射调用,解决不同版本返回值变更问题
|
// POI-5.2.0开始返回值有所变更,导致实际使用时提示方法未找到,此处使用反射调用,解决不同版本返回值变更问题
|
||||||
//this.handler.sharedStrings = xssfReader.getSharedStringsTable();
|
//this.handler.sharedStrings = xssfReader.getSharedStringsTable();
|
||||||
this.handler.sharedStrings = ReflectUtil.invoke(xssfReader, "getSharedStringsTable");
|
this.handler.sharedStrings = MethodUtil.invoke(xssfReader, "getSharedStringsTable");
|
||||||
|
|
||||||
return readSheets(xssfReader, idOrRidOrSheetName);
|
return readSheets(xssfReader, idOrRidOrSheetName);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user