【反射】Method类

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从方法的注解中获取指定类型的注解

相关推荐
代码之光_198019 分钟前
保障性住房管理:SpringBoot技术优势分析
java·spring boot·后端
ajsbxi25 分钟前
苍穹外卖学习记录
java·笔记·后端·学习·nginx·spring·servlet
StayInLove44 分钟前
G1垃圾回收器日志详解
java·开发语言
对许1 小时前
SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder“
java·log4j
鹿屿二向箔1 小时前
基于SSM(Spring + Spring MVC + MyBatis)框架的咖啡馆管理系统
spring·mvc·mybatis
无尽的大道1 小时前
Java字符串深度解析:String的实现、常量池与性能优化
java·开发语言·性能优化
小鑫记得努力1 小时前
Java类和对象(下篇)
java
binishuaio1 小时前
Java 第11天 (git版本控制器基础用法)
java·开发语言·git
zz.YE1 小时前
【Java SE】StringBuffer
java·开发语言
老友@1 小时前
aspose如何获取PPT放映页“切换”的“持续时间”值
java·powerpoint·aspose