This commit is contained in:
Looly 2024-05-15 17:31:33 +08:00
parent b921895917
commit 56c076d2f6
8 changed files with 103 additions and 342 deletions

View File

@ -28,6 +28,16 @@ import java.lang.reflect.Method;
*/
public class MethodInvoker implements Invoker {
/**
* 创建方法调用器
*
* @param method 方法
* @return 方法调用器
*/
public static MethodInvoker of(final Method method) {
return new MethodInvoker(method);
}
private final Method method;
private final Class<?>[] paramTypes;
private final Class<?> type;
@ -43,6 +53,7 @@ public class MethodInvoker implements Invoker {
this.paramTypes = method.getParameterTypes();
if (paramTypes.length == 1) {
// setter方法读取参数类型
type = paramTypes[0];
} else {
type = method.getReturnType();
@ -64,27 +75,44 @@ public class MethodInvoker implements Invoker {
return this;
}
@SuppressWarnings("unchecked")
@Override
public <T> T invoke(final Object target, final Object... args) throws HutoolException{
public <T> T invoke(Object target, final Object... args) throws HutoolException{
if(this.checkArgs){
checkArgs(args);
}
final Method method = this.method;
// static方法调用则target为null
if(ModifierUtil.isStatic(method)){
target = null;
}
// 根据方法定义的参数类型将用户传入的参数规整和转换
final Object[] actualArgs = MethodUtil.actualArgs(method, args);
try {
return MethodHandleUtil.invoke(target, method, args);
return MethodHandleUtil.invokeExact(target, method, actualArgs);
} catch (final Exception e) {
// 传统反射方式执行方法
try {
return (T) method.invoke(ModifierUtil.isStatic(method) ? null : target, MethodUtil.actualArgs(method, args));
return (T) method.invoke(target, actualArgs);
} catch (final IllegalAccessException | InvocationTargetException ex) {
throw new HutoolException(ex);
}
}
}
/**
* 执行静态方法
*
* @param <T> 对象类型
* @param args 参数对象
* @return 结果
* @throws HutoolException 多种异常包装
*/
public <T> T invokeStatic(final Object... args) throws HutoolException {
return invoke(null, args);
}
@Override
public Class<?> getType() {
return this.type;

View File

@ -45,6 +45,13 @@ public class MethodUtil {
*/
private static final WeakConcurrentMap<Class<?>, MethodReflect> METHODS_CACHE = new WeakConcurrentMap<>();
/**
* 清除方法缓存
*/
synchronized static void clearCache() {
METHODS_CACHE.clear();
}
// region ----- getMethods
/**
@ -255,7 +262,7 @@ public class MethodUtil {
/**
* 获得一个类中所有方法列表包括其父类中的方法
*
* @param clazz {@code null}
* @param clazz {@code null}
* @param predicate 方法过滤器{@code null}表示无过滤
* @return 方法列表
* @throws SecurityException 安全检查异常
@ -267,7 +274,7 @@ public class MethodUtil {
/**
* 获得本类及其父类所有Public方法
*
* @param clazz 查找方法的类
* @param clazz 查找方法的类
* @return 过滤后的方法列表
*/
public static Method[] getPublicMethods(final Class<?> clazz) {
@ -288,7 +295,7 @@ public class MethodUtil {
/**
* 获得类中所有直接声明方法不包括其父类中的方法
*
* @param clazz {@code null}
* @param clazz {@code null}
* @return 方法列表
* @throws SecurityException 安全检查异常
*/
@ -529,7 +536,7 @@ public class MethodUtil {
* @throws HutoolException 一些列异常的包装
*/
public static <T> T invokeWithCheck(final Object obj, final Method method, final Object... args) throws HutoolException {
return (new MethodInvoker(method)).setCheckArgs(true).invoke(obj, args);
return MethodInvoker.of(method).setCheckArgs(true).invoke(obj, args);
}
/**
@ -553,7 +560,7 @@ public class MethodUtil {
* @see MethodHandleUtil#invoke(Object, Method, Object...)
*/
public static <T> T invoke(final Object obj, final Method method, final Object... args) throws HutoolException {
return (new MethodInvoker(method)).invoke(obj, args);
return MethodInvoker.of(method).invoke(obj, args);
}
/**

View File

@ -26,7 +26,7 @@ import java.util.Map;
public class ConstructorUtilTest {
@Test
public void noneStaticInnerClassTest() {
final ReflectUtilTest.NoneStaticClass testAClass = ConstructorUtil.newInstanceIfPossible(ReflectUtilTest.NoneStaticClass.class);
final ReflectTestBeans.NoneStaticClass testAClass = ConstructorUtil.newInstanceIfPossible(ReflectTestBeans.NoneStaticClass.class);
Assertions.assertNotNull(testAClass);
Assertions.assertEquals(2, testAClass.getA());
}

View File

@ -22,34 +22,34 @@ public class FieldUtilTest {
@Test
public void getFieldTest() {
// 能够获取到父类字段
final Field privateField = FieldUtil.getField(ReflectUtilTest.TestSubClass.class, "privateField");
final Field privateField = FieldUtil.getField(ReflectTestBeans.TestSubClass.class, "privateField");
Assertions.assertNotNull(privateField);
}
@Test
public void getFieldsTest() {
// 能够获取到父类字段
final Field[] fields = FieldUtil.getFields(ReflectUtilTest.TestSubClass.class);
final Field[] fields = FieldUtil.getFields(ReflectTestBeans.TestSubClass.class);
Assertions.assertEquals(4, fields.length);
}
@Test
public void setFieldTest() {
final ReflectUtilTest.AClass testClass = new ReflectUtilTest.AClass();
final ReflectTestBeans.AClass testClass = new ReflectTestBeans.AClass();
FieldUtil.setFieldValue(testClass, "a", "111");
Assertions.assertEquals(111, testClass.getA());
}
@Test
public void getDeclaredField() {
final Field noField = FieldUtil.getField(ReflectUtilTest.TestSubClass.class, "noField");
final Field noField = FieldUtil.getField(ReflectTestBeans.TestSubClass.class, "noField");
Assertions.assertNull(noField);
// 获取不到父类字段
final Field field = FieldUtil.getDeclearField(ReflectUtilTest.TestSubClass.class, "field");
final Field field = FieldUtil.getDeclearField(ReflectTestBeans.TestSubClass.class, "field");
Assertions.assertNull(field);
final Field subField = FieldUtil.getField(ReflectUtilTest.TestSubClass.class, "subField");
final Field subField = FieldUtil.getField(ReflectTestBeans.TestSubClass.class, "subField");
Assertions.assertNotNull(subField);
}

View File

@ -78,6 +78,20 @@ public class MethodHandleUtilTest {
Assertions.assertEquals("Duck 78", result);
}
@Test
public void testInvokeExact() {
final Duck duck = new BigDuck();
final Method method = MethodUtil.getMethod(BigDuck.class, "toString");
final Object[] args = {};
// 执行测试方法
final String result = MethodHandleUtil.invokeExact(duck, method, args);
// 验证结果
Assertions.assertEquals(duck.toString(), result);
}
interface Duck {
default String quack() {
return "Quack";
@ -102,5 +116,10 @@ public class MethodHandleUtilTest {
private static String getPrivateStaticValue(){
return "private static value";
}
@Override
public String toString() {
return super.toString();
}
}
}

View File

@ -15,14 +15,14 @@ package org.dromara.hutool.core.reflect;
import lombok.Data;
/**
* 反射工具类单元测试
* 反射工具用于测试的类
*
* @author Looly
*/
public class ReflectUtilTest {
public class ReflectTestBeans {
@Data
static class AClass {
protected static class AClass {
private int a;
}
@ -33,7 +33,7 @@ public class ReflectUtilTest {
}
@Data
static class TestBenchClass {
protected static class TestBenchClass {
private int a;
private String b;
private String c;
@ -69,7 +69,7 @@ public class ReflectUtilTest {
void getB();
}
interface TestInterface3 extends TestInterface2 {
protected interface TestInterface3 extends TestInterface2 {
void get3();
}
@ -88,7 +88,7 @@ public class ReflectUtilTest {
}
@SuppressWarnings("RedundantMethodOverride")
class C2 extends C1 {
protected class C2 extends C1 {
@Override
public void getA() {
@ -108,7 +108,7 @@ public class ReflectUtilTest {
}
@SuppressWarnings({"InnerClassMayBeStatic", "unused"})
class TestSubClass extends TestClass {
protected class TestSubClass extends TestClass {
private String subField;
private void privateSubMethod() {

View File

@ -1,294 +0,0 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* https://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.core.reflect.method;
import lombok.SneakyThrows;
import org.dromara.hutool.core.annotation.Alias;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
/**
* test for {@link MethodScanner2}
*
* @author huangchengxing
*/
class MethodScannerTest {
@Test
void testGetMethods() {
Assertions.assertEquals(0, MethodScanner2.getMethods(null).length);
final Method[] actual = MethodScanner2.getMethods(Child.class);
Assertions.assertSame(actual, MethodScanner2.getMethods(Child.class));
final Method[] expected = Child.class.getMethods();
Assertions.assertArrayEquals(expected, actual);
}
@Test
void testGetDeclaredMethods() {
Assertions.assertEquals(0, MethodScanner2.getDeclaredMethods(null).length);
final Method[] actual = MethodScanner2.getDeclaredMethods(Child.class);
Assertions.assertSame(actual, MethodScanner2.getDeclaredMethods(Child.class));
final Method[] expected = Child.class.getDeclaredMethods();
Assertions.assertArrayEquals(expected, actual);
}
@Test
void testGetAllMethods() {
Assertions.assertEquals(0, MethodScanner2.getAllMethods(null).length);
final Method[] actual = MethodScanner2.getAllMethods(Child.class);
// get declared method from childparentgrandparent
final Method[] expected = Stream.of(Child.class, Parent.class, Interface.class, Object.class)
.flatMap(c -> Stream.of(MethodScanner2.getDeclaredMethods(c)))
.toArray(Method[]::new);
Assertions.assertArrayEquals(expected, actual);
}
@Test
void testClearCaches() {
final Method[] declaredMethods = MethodScanner2.getDeclaredMethods(Child.class);
Assertions.assertSame(declaredMethods, MethodScanner2.getDeclaredMethods(Child.class));
final Method[] methods = MethodScanner2.getMethods(Child.class);
Assertions.assertSame(methods, MethodScanner2.getMethods(Child.class));
// clear method cache
MethodScanner2.clearCaches();
Assertions.assertNotSame(declaredMethods, MethodScanner2.getDeclaredMethods(Child.class));
Assertions.assertNotSame(methods, MethodScanner2.getMethods(Child.class));
}
@SneakyThrows
@Test
void testFindWithMetadataFromSpecificMethods() {
Assertions.assertTrue(MethodScanner2.findWithMetadataFromSpecificMethods(null, m -> m.getAnnotation(Annotation.class)).isEmpty());
final Method[] methods = MethodScanner2.getMethods(Child.class);
final Map<Method, Annotation> actual = MethodScanner2.findWithMetadataFromSpecificMethods(methods, m -> m.getAnnotation(Annotation.class));
Assertions.assertEquals(1, actual.size());
// check method
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertTrue(actual.containsKey(expectedMethod));
// check annotation
final Annotation expectedAnnotation = expectedMethod.getAnnotation(Annotation.class);
Assertions.assertEquals(expectedAnnotation, actual.get(expectedMethod));
}
@SneakyThrows
@Test
void testFindFromSpecificMethods() {
final Method[] methods = MethodScanner2.getMethods(Child.class);
final Set<Method> actual = MethodScanner2.findFromSpecificMethods(methods, m -> m.getAnnotation(Annotation.class));
Assertions.assertEquals(1, actual.size());
// check method
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertTrue(actual.contains(expectedMethod));
}
@SneakyThrows
@Test
void testGetWithMetadataFromSpecificMethods() {
// find first oneArgMethod method
final Method[] methods = MethodScanner2.getMethods(Child.class);
final Map.Entry<Method, Boolean> actual = MethodScanner2.getWithMetadataFromSpecificMethods(methods,
(method -> method.getName().equals("oneArgMethod") ? true : null));
Assertions.assertNotNull(actual);
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertEquals(expectedMethod, actual.getKey());
Assertions.assertTrue(actual.getValue());
}
@SneakyThrows
@Test
void testGetFromSpecificMethods() {
// find first oneArgMethod method
final Method[] methods = MethodScanner2.getMethods(Child.class);
final Method actual = MethodScanner2.getFromSpecificMethods(methods, method ->
method.getName().equals("oneArgMethod") ? true : null);
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertEquals(expectedMethod, actual);
}
@SneakyThrows
@Test
void testFindWithMetadataFromMethods() {
final Map<Method, Annotation> actual = MethodScanner2.findWithMetadataFromMethods(Child.class, m -> m.getAnnotation(Annotation.class));
Assertions.assertEquals(1, actual.size());
// check method
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertTrue(actual.containsKey(expectedMethod));
// check annotation
final Annotation expectedAnnotation = expectedMethod.getAnnotation(Annotation.class);
Assertions.assertEquals(expectedAnnotation, actual.get(expectedMethod));
}
@SneakyThrows
@Test
void testFindFromMethods() {
final Set<Method> actual = MethodScanner2.findFromMethods(Child.class, m -> m.getAnnotation(Annotation.class));
Assertions.assertEquals(1, actual.size());
// check method
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertTrue(actual.contains(expectedMethod));
}
@SneakyThrows
@Test
void testGetWithMetadataFromMethods() {
final Map.Entry<Method, Annotation> actual = MethodScanner2.getWithMetadataFromMethods(Child.class, m -> m.getAnnotation(Annotation.class));
Assertions.assertNotNull(actual);
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertEquals(expectedMethod, actual.getKey());
final Annotation expectedAnnotation = expectedMethod.getAnnotation(Annotation.class);
Assertions.assertEquals(expectedAnnotation, actual.getValue());
}
@SneakyThrows
@Test
void testGetFromMethods() {
final Method actual = MethodScanner2.getFromMethods(Child.class, m -> m.getAnnotation(Annotation.class));
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertEquals(expectedMethod, actual);
}
@SneakyThrows
@Test
void testFindWithMetadataFromDeclaredMethods() {
final Map<Method, Annotation> actual = MethodScanner2.findWithMetadataFromDeclaredMethods(Parent.class, m -> m.getAnnotation(Annotation.class));
Assertions.assertEquals(1, actual.size());
// check method
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertTrue(actual.containsKey(expectedMethod));
// check annotation
final Annotation expectedAnnotation = expectedMethod.getAnnotation(Annotation.class);
Assertions.assertEquals(expectedAnnotation, actual.get(expectedMethod));
}
@SneakyThrows
@Test
void testFindFromDeclaredMethods() {
final Set<Method> actual = MethodScanner2.findFromDeclaredMethods(Parent.class, m -> m.getAnnotation(Annotation.class));
Assertions.assertEquals(1, actual.size());
// check method
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertTrue(actual.contains(expectedMethod));
}
@SneakyThrows
@Test
void testGetWithMetadataFromDeclaredMethods() {
final Map.Entry<Method, Annotation> actual = MethodScanner2.getWithMetadataFromDeclaredMethods(Parent.class, m -> m.getAnnotation(Annotation.class));
Assertions.assertNotNull(actual);
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertEquals(expectedMethod, actual.getKey());
final Annotation expectedAnnotation = expectedMethod.getAnnotation(Annotation.class);
Assertions.assertEquals(expectedAnnotation, actual.getValue());
}
@SneakyThrows
@Test
void testGetFromDeclaredMethods() {
final Method actual = MethodScanner2.getFromDeclaredMethods(Parent.class, m -> m.getAnnotation(Annotation.class));
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertEquals(expectedMethod, actual);
}
@SneakyThrows
@Test
void testFindWithMetadataFromAllMethods() {
final Map<Method, Annotation> actual = MethodScanner2.findWithMetadataFromAllMethods(Child.class, m -> m.getAnnotation(Annotation.class));
Assertions.assertEquals(1, actual.size());
// check method
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertTrue(actual.containsKey(expectedMethod));
// check annotation
final Annotation expectedAnnotation = expectedMethod.getAnnotation(Annotation.class);
Assertions.assertEquals(expectedAnnotation, actual.get(expectedMethod));
}
@SneakyThrows
@Test
void testFindFromAllMethods() {
final Set<Method> actual = MethodScanner2.findFromAllMethods(Child.class, m -> m.getAnnotation(Annotation.class));
Assertions.assertEquals(1, actual.size());
// check method
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertTrue(actual.contains(expectedMethod));
}
@SneakyThrows
@Test
void testGetWithMetadataFromAllMethods() {
Assertions.assertNull(MethodScanner2.getWithMetadataFromAllMethods(Child.class, m -> m.getAnnotation(Alias.class)));
final Map.Entry<Method, Annotation> actual = MethodScanner2.getWithMetadataFromAllMethods(Child.class, m -> m.getAnnotation(Annotation.class));
Assertions.assertNotNull(actual);
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertEquals(expectedMethod, actual.getKey());
final Annotation expectedAnnotation = expectedMethod.getAnnotation(Annotation.class);
Assertions.assertEquals(expectedAnnotation, actual.getValue());
}
@SneakyThrows
@Test
void testGetFromAllMethods() {
final Method actual = MethodScanner2.getFromAllMethods(Child.class, m -> m.getAnnotation(Annotation.class));
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
Assertions.assertEquals(expectedMethod, actual);
}
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Annotation {
String value() default "default";
}
@Annotation("Interface")
public interface Interface {
static void staticMethod() {
}
void noneArgMethod();
void oneArgMethod(String arg);
}
public static class Parent implements Interface {
@Override
public void noneArgMethod() { }
@Annotation("oneArgMethod")
@Override
public void oneArgMethod(final String arg) { }
}
public static class Child extends Parent implements Interface {
}
}

View File

@ -10,14 +10,15 @@
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.core.reflect;
package org.dromara.hutool.core.reflect.method;
import lombok.Data;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.date.StopWatch;
import org.dromara.hutool.core.lang.Console;
import org.dromara.hutool.core.lang.test.bean.ExamInfoDict;
import org.dromara.hutool.core.reflect.method.MethodUtil;
import org.dromara.hutool.core.reflect.ClassUtil;
import org.dromara.hutool.core.reflect.ReflectTestBeans;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.JdkUtil;
import org.junit.jupiter.api.Assertions;
@ -26,7 +27,7 @@ import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
public class MethodUtilTest {
public class MethodUtilTest extends ReflectTestBeans {
private static final boolean isGteJdk15 = getJavaVersion() >= 15;
/**
@ -87,14 +88,14 @@ public class MethodUtilTest {
@Test
public void invokeTest() {
final ReflectUtilTest.AClass testClass = new ReflectUtilTest.AClass();
final AClass testClass = new AClass();
MethodUtil.invoke(testClass, "setA", 10);
Assertions.assertEquals(10, testClass.getA());
}
@Test
public void getDeclaredMethodsTest() {
Class<?> type = ReflectUtilTest.TestBenchClass.class;
Class<?> type = TestBenchClass.class;
Method[] methods = type.getDeclaredMethods();
Assertions.assertArrayEquals(methods, MethodUtil.getDeclaredMethods(type));
Assertions.assertSame(MethodUtil.getDeclaredMethods(type), MethodUtil.getDeclaredMethods(type));
@ -108,19 +109,19 @@ public class MethodUtilTest {
@Disabled
public void getMethodBenchTest() {
// 预热
getMethodWithReturnTypeCheck(ReflectUtilTest.TestBenchClass.class, false, "getH");
getMethodWithReturnTypeCheck(TestBenchClass.class, false, "getH");
final StopWatch timer = new StopWatch();
timer.start();
for (int i = 0; i < 100000000; i++) {
MethodUtil.getMethod(ReflectUtilTest.TestBenchClass.class, false, "getH");
MethodUtil.getMethod(TestBenchClass.class, false, "getH");
}
timer.stop();
Console.log(timer.getLastTaskTimeMillis());
timer.start();
for (int i = 0; i < 100000000; i++) {
getMethodWithReturnTypeCheck(ReflectUtilTest.TestBenchClass.class, false, "getH");
getMethodWithReturnTypeCheck(TestBenchClass.class, false, "getH");
}
timer.stop();
Console.log(timer.getLastTaskTimeMillis());
@ -150,60 +151,60 @@ public class MethodUtilTest {
@Test
public void getMethodsFromClassExtends() {
// 继承情况下需解决方法去重问题
Method[] methods = MethodUtil.getMethods(ReflectUtilTest.C2.class);
Method[] methods = MethodUtil.getMethods(C2.class);
Assertions.assertEquals(isGteJdk15 ? 14 : 15, methods.length);
// 排除Object中的方法
// 3个方法包括类
methods = MethodUtil.getMethodsDirectly(ReflectUtilTest.C2.class, true, false);
methods = MethodUtil.getMethodsDirectly(C2.class, true, false);
Assertions.assertEquals(3, methods.length);
// getA属于本类
Assertions.assertEquals("public void org.dromara.hutool.core.reflect.ReflectUtilTest$C2.getA()", methods[0].toString());
Assertions.assertEquals("public void org.dromara.hutool.core.reflect.ReflectTestBeans$C2.getA()", methods[0].toString());
// getB属于父类
Assertions.assertEquals("public void org.dromara.hutool.core.reflect.ReflectUtilTest$C1.getB()", methods[1].toString());
Assertions.assertEquals("public void org.dromara.hutool.core.reflect.ReflectTestBeans$C1.getB()", methods[1].toString());
// getC属于接口中的默认方法
Assertions.assertEquals("public default void org.dromara.hutool.core.reflect.ReflectUtilTest$TestInterface1.getC()", methods[2].toString());
Assertions.assertEquals("public default void org.dromara.hutool.core.reflect.ReflectTestBeans$TestInterface1.getC()", methods[2].toString());
}
@Test
public void getMethodsFromInterfaceTest() {
// 对于接口直接调用Class.getMethods方法获取所有方法因为接口都是public方法
// 因此此处得到包括TestInterface1TestInterface2TestInterface3中一共4个方法
final Method[] methods = MethodUtil.getMethods(ReflectUtilTest.TestInterface3.class);
final Method[] methods = MethodUtil.getMethods(TestInterface3.class);
Assertions.assertEquals(4, methods.length);
// 接口里调用getMethods和getPublicMethods效果相同
final Method[] publicMethods = MethodUtil.getPublicMethods(ReflectUtilTest.TestInterface3.class);
final Method[] publicMethods = MethodUtil.getPublicMethods(TestInterface3.class);
Assertions.assertArrayEquals(methods, publicMethods);
}
@Test
public void getPublicMethod() {
final Method superPublicMethod = MethodUtil.getPublicMethod(ReflectUtilTest.TestSubClass.class, false, "publicMethod");
final Method superPublicMethod = MethodUtil.getPublicMethod(TestSubClass.class, false, "publicMethod");
Assertions.assertNotNull(superPublicMethod);
final Method superPrivateMethod = MethodUtil.getPublicMethod(ReflectUtilTest.TestSubClass.class, false, "privateMethod");
final Method superPrivateMethod = MethodUtil.getPublicMethod(TestSubClass.class, false, "privateMethod");
Assertions.assertNull(superPrivateMethod);
final Method publicMethod = MethodUtil.getPublicMethod(ReflectUtilTest.TestSubClass.class, false, "publicSubMethod");
final Method publicMethod = MethodUtil.getPublicMethod(TestSubClass.class, false, "publicSubMethod");
Assertions.assertNotNull(publicMethod);
final Method privateMethod = MethodUtil.getPublicMethod(ReflectUtilTest.TestSubClass.class, false, "privateSubMethod");
final Method privateMethod = MethodUtil.getPublicMethod(TestSubClass.class, false, "privateSubMethod");
Assertions.assertNull(privateMethod);
}
@Test
public void getDeclaredMethod() {
final Method noMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "noMethod");
final Method noMethod = MethodUtil.getMethod(TestSubClass.class, "noMethod");
Assertions.assertNull(noMethod);
final Method privateMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "privateMethod");
final Method privateMethod = MethodUtil.getMethod(TestSubClass.class, "privateMethod");
Assertions.assertNotNull(privateMethod);
final Method publicMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "publicMethod");
final Method publicMethod = MethodUtil.getMethod(TestSubClass.class, "publicMethod");
Assertions.assertNotNull(publicMethod);
final Method publicSubMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "publicSubMethod");
final Method publicSubMethod = MethodUtil.getMethod(TestSubClass.class, "publicSubMethod");
Assertions.assertNotNull(publicSubMethod);
final Method privateSubMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "privateSubMethod");
final Method privateSubMethod = MethodUtil.getMethod(TestSubClass.class, "privateSubMethod");
Assertions.assertNotNull(privateSubMethod);
}