【反射】Method类

Method类中包含了方法定义的详细信息,可以使用Method类中提供的方法来获取方法的信息,下面我们先获取Method对象,再介绍如何使用Method类中提供的方法。

一、准备工作

在src/test/java目录的cn.horse.reflect.entity包下新建BaseEntity类、UserInfoEntity类;新建EntityAnnotation、InheritedEntityAnnotation、UserInfoEntityAnnotation注解

BaseEntity类:

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类:

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注解:

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注解:

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注解:

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类:

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类:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值