Method类中包含了方法定义的详细信息,可以使用Method类中提供的方法来获取方法的信息,下面我们先获取Method对象,再介绍如何使用Method类中提供的方法。
一、准备工作
在src/test/java目录的cn.horse.reflect.entity包下新建BaseEntity类、UserInfoEntity类;新建EntityAnnotation、InheritedEntityAnnotation、UserInfoEntityAnnotation注解
BaseEntity 类:
java
package cn.horse.reflect.entity;
@EntityAnnotation
@InheritedEntityAnnotation
public abstract class BaseEntity {
@EntityAnnotation
@InheritedEntityAnnotation
public Long id;
@InheritedEntityAnnotation
public BaseEntity() { }
@EntityAnnotation
@InheritedEntityAnnotation
public BaseEntity(Long id) {
this.id = id;
}
@EntityAnnotation
@InheritedEntityAnnotation
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
}
UserInfoEntity 类:
java
package cn.horse.reflect.entity;
@UserInfoEntityAnnotation
public class UserInfoEntity extends BaseEntity {
@UserInfoEntityAnnotation
public String name;
@UserInfoEntityAnnotation
private Integer age;
@UserInfoEntityAnnotation
private UserInfoEntity() {
}
@UserInfoEntityAnnotation
public UserInfoEntity(Long id) {
super(id);
}
@UserInfoEntityAnnotation
public UserInfoEntity(Long id, String name, Integer age) {
super(id);
this.name = name;
this.age = age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getAge() {
return age;
}
private String getName() {
return name;
}
private void check() { }
@UserInfoEntityAnnotation
@Override
public void setId(Long id) {
super.setId(id);
}
}
EntityAnnotation 注解:
java
package cn.horse.reflect.entity;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface EntityAnnotation {
}
InheritedEntityAnnotation 注解:
java
package cn.horse.reflect.entity;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface InheritedEntityAnnotation {
}
UserInfoEntityAnnotation 注解:
java
package cn.horse.reflect.entity;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserInfoEntityAnnotation {
}
二、获取Method对象
在src/test/java目录的cn.horse.reflect包下新建GetMethodInstanceTests测试类
GetMethodInstanceTests 类:
java
package cn.horse.reflect;
import cn.horse.reflect.entity.UserInfoEntity;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
public class GetMethodInstanceTests {
static final Class<UserInfoEntity> USER_INFO_ENTITY_CLASS = UserInfoEntity.class;
@Test
public void testGetMethods() {
// getMethods 获取当前类及其父类中使用public定义的方法
Collection<String> methodNameList = Arrays.stream(USER_INFO_ENTITY_CLASS.getMethods()).map(Method::getName).collect(Collectors.toSet());
List<String> expectedMethodNameList = Arrays.asList("getAge", "setAge", "getId", "setId", "getClass", "hashCode", "equals", "toString", "notify", "notifyAll", "wait");
assertThat(methodNameList.size()).isEqualTo(expectedMethodNameList.size());
assertThat(methodNameList).containsAll(expectedMethodNameList);
}
@Test
public void testGetMethod() throws NoSuchMethodException {
UserInfoEntity userInfoEntity = new UserInfoEntity(200L, "张三", 10);
assertThat(USER_INFO_ENTITY_CLASS.getMethod("getId")).isNotNull();
assertThatExceptionOfType(NoSuchMethodException.class).isThrownBy(() -> { USER_INFO_ENTITY_CLASS.getMethod("getName"); });
assertThat(USER_INFO_ENTITY_CLASS.getMethod("getAge")).isNotNull();
}
@Test
public void testGetDeclaredMethods() {
// getDeclaredMethods 获取当前类中定义的所有方法(不能获取父类中定义的方法)
Collection<String> declaredMethodNameList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredMethods()).map(Method::getName).collect(Collectors.toSet());
List<String> expectedDeclaredMethodNameList = Arrays.asList("setAge", "getAge", "setId", "getName", "check");
assertThat(declaredMethodNameList.size()).isEqualTo(expectedDeclaredMethodNameList.size());
assertThat(declaredMethodNameList).containsAll(expectedDeclaredMethodNameList);
}
@Test
public void testGetDeclaredMethod() throws NoSuchMethodException {
UserInfoEntity userInfoEntity = new UserInfoEntity(200L, "张三", 10);
assertThatExceptionOfType(NoSuchMethodException.class).isThrownBy(() -> { USER_INFO_ENTITY_CLASS.getDeclaredMethod("getId"); });
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("getName")).isNotNull();
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("getAge")).isNotNull();
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("check")).isNotNull();
}
}
单元测试方法介绍:
testGetMethods : 使用getMethods方法获取当前类及其父类中使用public定义的所有字段
testGetMethod : 使用getMethod方法获取当前类及其父类中使用public定义的指定字段
testGetDeclaredMethods : 使用getDeclaredMethods方法获取当前类中定义的所有字段
testGetDeclaredMethod : 使用getDeclaredMethod方法获取当前类中定义的指定字段
三、Method类中方法的使用
在src/test/java目录的cn.horse.reflect包下新建MethodInstanceMethodTests测试类
MethodInstanceMethodTests 类:
java
package cn.horse.reflect;
import cn.horse.reflect.entity.*;
import org.junit.jupiter.api.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
public class MethodInstanceMethodTests {
static final Class<UserInfoEntity> USER_INFO_ENTITY_CLASS = UserInfoEntity.class;
@Test
public void testGetDeclaringClass() throws NoSuchMethodException {
assertThat(USER_INFO_ENTITY_CLASS.getMethod("getId").getDeclaringClass()).isEqualTo(BaseEntity.class);
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("getName").getDeclaringClass()).isEqualTo(UserInfoEntity.class);
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("getAge").getDeclaringClass()).isEqualTo(UserInfoEntity.class);
}
@Test
public void testGetReturnType() throws NoSuchMethodException {
assertThat(USER_INFO_ENTITY_CLASS.getMethod("getId").getReturnType()).isEqualTo(Long.class);
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("getName").getReturnType()).isEqualTo(String.class);
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("getAge").getReturnType()).isEqualTo(Integer.class);
}
@Test
public void testGetName() throws NoSuchMethodException {
assertThat(USER_INFO_ENTITY_CLASS.getMethod("getId").getName()).isEqualTo("getId");
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("getName").getName()).isEqualTo("getName");
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("getAge").getName()).isEqualTo("getAge");
}
@Test
public void testGetModifiers() throws NoSuchMethodException {
assertThat(Modifier.isPublic(USER_INFO_ENTITY_CLASS.getMethod("getId").getModifiers())).isTrue();
assertThat(Modifier.isPrivate(USER_INFO_ENTITY_CLASS.getDeclaredMethod("getName").getModifiers())).isTrue();
assertThat(Modifier.isPublic(USER_INFO_ENTITY_CLASS.getDeclaredMethod("getAge").getModifiers())).isTrue();
}
@Test
public void testInvokeMethodGetValue() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
UserInfoEntity userInfoEntity = new UserInfoEntity(200L, "张三", 10);
assertThat(USER_INFO_ENTITY_CLASS.getMethod("getId").invoke(userInfoEntity)).isEqualTo(200L);
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("getAge").invoke(userInfoEntity)).isEqualTo(10);
// 获取getName方法
Method nameMethod = USER_INFO_ENTITY_CLASS.getDeclaredMethod("getName");
assertThatExceptionOfType(IllegalAccessException.class).isThrownBy(() -> { nameMethod.invoke(userInfoEntity); });
nameMethod.setAccessible(true);
assertThat(nameMethod.invoke(userInfoEntity)).isEqualTo("张三");
}
@Test
public void testInvokeMethodSetValue() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
UserInfoEntity userInfoEntity = new UserInfoEntity(200L, "张三", 10);
USER_INFO_ENTITY_CLASS.getDeclaredMethod("setId", Long.class).invoke(userInfoEntity, 300L);
USER_INFO_ENTITY_CLASS.getDeclaredMethod("setAge", Integer.class).invoke(userInfoEntity, 20);
assertThat(userInfoEntity.getId()).isEqualTo(300L);
assertThat(userInfoEntity.name).isEqualTo("张三");
assertThat(userInfoEntity.getAge()).isEqualTo(20);
}
@Test
public void testGetAnnotations() throws NoSuchMethodException {
Collection<Class<? extends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredMethod("setId", Long.class).getAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
List<Class<? extends Annotation>> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
assertThat(annotationList).containsAll(expectedAnnotationList);
}
@Test
public void testGetAnnotationsByType() throws NoSuchMethodException {
Collection<Class<? extends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredMethod("setId", Long.class).getAnnotationsByType(UserInfoEntityAnnotation.class)).map(Annotation::annotationType).collect(Collectors.toList());
List<Class<? extends Annotation>> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
assertThat(annotationList).containsAll(expectedAnnotationList);
}
@Test
public void testGetAnnotation() throws NoSuchMethodException {
assertThat(USER_INFO_ENTITY_CLASS.getMethod("setId", Long.class).getAnnotation(EntityAnnotation.class)).isNull();
assertThat(USER_INFO_ENTITY_CLASS.getMethod("setId", Long.class).getAnnotation(InheritedEntityAnnotation.class)).isNull();
assertThat(USER_INFO_ENTITY_CLASS.getMethod("setId", Long.class).getAnnotation(UserInfoEntityAnnotation.class)).isNotNull();
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("setId", Long.class).getAnnotation(EntityAnnotation.class)).isNull();
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("setId", Long.class).getAnnotation(InheritedEntityAnnotation.class)).isNull();
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("setId", Long.class).getAnnotation(UserInfoEntityAnnotation.class)).isNotNull();
}
@Test
public void testGetDeclaredAnnotations() throws NoSuchMethodException {
Collection<Class<? extends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredMethod("setId", Long.class).getDeclaredAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
List<Class<? extends Annotation>> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
assertThat(annotationList).containsAll(expectedAnnotationList);
}
@Test
public void testGetDeclaredAnnotationsByType() throws NoSuchMethodException {
Collection<Class<? extends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredMethod("setId", Long.class).getDeclaredAnnotationsByType(UserInfoEntityAnnotation.class)).map(Annotation::annotationType).collect(Collectors.toList());
List<Class<? extends Annotation>> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
assertThat(annotationList).containsAll(expectedAnnotationList);
}
@Test
public void testGetDeclaredAnnotation() throws NoSuchMethodException {
assertThat(USER_INFO_ENTITY_CLASS.getMethod("setId", Long.class).getDeclaredAnnotation(EntityAnnotation.class)).isNull();
assertThat(USER_INFO_ENTITY_CLASS.getMethod("setId", Long.class).getDeclaredAnnotation(InheritedEntityAnnotation.class)).isNull();
assertThat(USER_INFO_ENTITY_CLASS.getMethod("setId", Long.class).getDeclaredAnnotation(UserInfoEntityAnnotation.class)).isNotNull();
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("setId", Long.class).getDeclaredAnnotation(EntityAnnotation.class)).isNull();
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("setId", Long.class).getDeclaredAnnotation(InheritedEntityAnnotation.class)).isNull();
assertThat(USER_INFO_ENTITY_CLASS.getDeclaredMethod("setId", Long.class).getDeclaredAnnotation(UserInfoEntityAnnotation.class)).isNotNull();
}
}
单元测试方法介绍:
testGetDeclaringClass : 使用getDeclaringClass方法获取到方法所在类(声明类)的Class对象
testGetReturnType : 使用getReturnType方法获取方法的返回值类型
testGetName : 使用getName方法获取方法的名称
testGetModifiers : 使用getModifiers获取修饰符,并使用Modifier类提供的静态方法依次判断了是否使用了public、private、protected等修饰符
testInvokeMethodGetValue : 使用invoke方法调用方法,如果方法不可访问会抛出IllegalAccessException异常,使用setAccessible方法可以控制访问权限。
testInvokeMethodSetValue : 使用invoke方法调用方法,如果方法不可访问会抛出IllegalAccessException异常,使用setAccessible方法可以控制访问权限。
testGetAnnotations : 使用getAnnotations获取方法的所有注解
testGetAnnotationsByType : 使用getAnnotationsByType从方法的注解中获取指定类型的注解
testGetAnnotation : 使用getAnnotation从方法的注解中获取指定类型的注解
testGetDeclaredAnnotations : 使用getDeclaredAnnotations获取方法的所有注解
testGetDeclaredAnnotationsByType : 使用getDeclaredAnnotationsByType从方法的注解中获取指定类型的注解
testGetDeclaredAnnotation : 使用getDeclaredAnnotation从方法的注解中获取指定类型的注解