【反射】Field类

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

一、准备工作

在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 {
}

二、获取Field对象

在src/test/java目录的cn.horse.reflect包下新建GetFieldInstanceTests测试类

GetFieldInstanceTests 类:

java 复制代码
package cn.horse.reflect;

import cn.horse.reflect.entity.UserInfoEntity;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;
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 GetFieldInstanceTests {

    static final Class<UserInfoEntity> USER_INFO_ENTITY_CLASS = UserInfoEntity.class;

    @Test
    public void testGetFields() {
        // getFields 获取当前类及其父类中使用public定义的字段
        Collection<String> fieldNameList = Arrays.stream(USER_INFO_ENTITY_CLASS.getFields()).map(Field::getName).collect(Collectors.toList());
        List<String> expectedFieldNameList = Arrays.asList("name", "id");
        assertThat(fieldNameList.size()).isEqualTo(expectedFieldNameList.size());
        assertThat(fieldNameList).containsAll(expectedFieldNameList);
    }

    @Test
    public void testGetField() throws NoSuchFieldException {
        assertThat(USER_INFO_ENTITY_CLASS.getField("id")).isNotNull();
        assertThat(USER_INFO_ENTITY_CLASS.getField("name")).isNotNull();
        assertThatExceptionOfType(NoSuchFieldException.class).isThrownBy(() -> { USER_INFO_ENTITY_CLASS.getField("age"); });
    }

    @Test
    public void testGetDeclaredFields() {
        // getDeclaredFields 获取当前类中定义的所有字段(不能获取父类中定义的字段)
        Collection<String> declaredFieldNameList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredFields()).map(Field::getName).collect(Collectors.toList());
        List<String> expectedDeclaredFieldNameList = Arrays.asList("name", "age");
        assertThat(declaredFieldNameList.size()).isEqualTo(expectedDeclaredFieldNameList.size());
        assertThat(declaredFieldNameList).containsAll(expectedDeclaredFieldNameList);
    }

    @Test
    public void testGetDeclaredField() throws NoSuchFieldException {
        assertThatExceptionOfType(NoSuchFieldException.class).isThrownBy(() -> { USER_INFO_ENTITY_CLASS.getDeclaredField("id"); });
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("name")).isNotNull();
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("age")).isNotNull();
    }
}

单元测试方法介绍:

testGetFields 使用getFields方法获取当前类及其父类中使用public定义的所有字段

testGetField 使用getField方法获取当前类及其父类中使用public定义的指定字段

testGetDeclaredFields 使用getDeclaredFields方法获取当前类中定义的所有字段

testGetDeclaredField 使用getDeclaredField方法获取当前类中定义的指定字段

三、Field类中方法的使用

在src/test/java目录的cn.horse.reflect包下新建FieldInstanceMethodTests测试类

FieldInstanceMethodTests 类:

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.Field;
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 FieldInstanceMethodTests {

    static final Class<UserInfoEntity> USER_INFO_ENTITY_CLASS = UserInfoEntity.class;

    @Test
    public void testGetDeclaringClass() throws NoSuchFieldException {
        assertThat(USER_INFO_ENTITY_CLASS.getField("id").getDeclaringClass()).isEqualTo(BaseEntity.class);
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("name").getDeclaringClass()).isEqualTo(UserInfoEntity.class);
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("age").getDeclaringClass()).isEqualTo(UserInfoEntity.class);
    }

    @Test
    public void testGetType() throws NoSuchFieldException {
        assertThat(USER_INFO_ENTITY_CLASS.getField("id").getType()).isEqualTo(Long.class);
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("name").getType()).isEqualTo(String.class);
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("age").getType()).isEqualTo(Integer.class);
    }

    @Test
    public void testGetName() throws NoSuchFieldException {
        assertThat(USER_INFO_ENTITY_CLASS.getField("id").getName()).isEqualTo("id");
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("name").getName()).isEqualTo("name");
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("age").getName()).isEqualTo("age");
    }

    @Test
    public void testGetModifiers() throws NoSuchFieldException {
        assertThat(Modifier.isPublic(USER_INFO_ENTITY_CLASS.getField("id").getModifiers())).isTrue();
        assertThat(Modifier.isPublic(USER_INFO_ENTITY_CLASS.getDeclaredField("name").getModifiers())).isTrue();
        assertThat(Modifier.isPrivate(USER_INFO_ENTITY_CLASS.getDeclaredField("age").getModifiers())).isTrue();
    }

    @Test
    public void testGetFieldValue() throws NoSuchFieldException, IllegalAccessException {
        UserInfoEntity userInfoEntity = new UserInfoEntity(200L, "张三", 10);
        assertThat(USER_INFO_ENTITY_CLASS.getField("id").get(userInfoEntity)).isEqualTo(200L);
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("name").get(userInfoEntity)).isEqualTo("张三");
        // 获取age字段
        Field ageField = USER_INFO_ENTITY_CLASS.getDeclaredField("age");
        assertThatExceptionOfType(IllegalAccessException.class).isThrownBy(() -> { ageField.get(userInfoEntity); });
        ageField.setAccessible(true);
        assertThat(ageField.get(userInfoEntity)).isEqualTo(10);
    }

    @Test
    public void testSetFieldValue() throws NoSuchFieldException, IllegalAccessException {
        UserInfoEntity userInfoEntity = new UserInfoEntity(200L, "张三", 10);
        USER_INFO_ENTITY_CLASS.getField("id").set(userInfoEntity, 300L);
        USER_INFO_ENTITY_CLASS.getDeclaredField("name").set(userInfoEntity, "李四");
        // 获取age字段
        Field ageField = USER_INFO_ENTITY_CLASS.getDeclaredField("age");
        assertThatExceptionOfType(IllegalAccessException.class).isThrownBy(() -> { ageField.set(userInfoEntity, 20); });
        ageField.setAccessible(true);
        ageField.set(userInfoEntity, 20);

        assertThat(userInfoEntity.getId()).isEqualTo(300L);
        assertThat(userInfoEntity.name).isEqualTo("李四");
        assertThat(userInfoEntity.getAge()).isEqualTo(20);
    }

    @Test
    public void testIdFieldGetAnnotations() throws NoSuchFieldException {
        Collection<Class<? extends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getField("id").getAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
        List<Class<? extends Annotation>> expectedAnnotationList = Arrays.asList(EntityAnnotation.class, InheritedEntityAnnotation.class);
        assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
        assertThat(annotationList).containsAll(expectedAnnotationList);
    }

    @Test
    public void testNameFieldGetAnnotations() throws NoSuchFieldException {
        Collection<Class<? extends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getField("name").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 testAgeFieldGetAnnotations() throws NoSuchFieldException {
        Collection<Class<? extends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredField("age").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 testFieldGetAnnotationsByType() throws NoSuchFieldException {
        Collection<Class<? extends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getField("name").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 testFieldGetAnnotation() throws NoSuchFieldException {
        assertThat(USER_INFO_ENTITY_CLASS.getField("id").getAnnotation(EntityAnnotation.class)).isNotNull();
        assertThat(USER_INFO_ENTITY_CLASS.getField("id").getAnnotation(InheritedEntityAnnotation.class)).isNotNull();
        assertThat(USER_INFO_ENTITY_CLASS.getField("id").getAnnotation(UserInfoEntityAnnotation.class)).isNull();
        assertThat(USER_INFO_ENTITY_CLASS.getField("name").getAnnotation(EntityAnnotation.class)).isNull();
        assertThat(USER_INFO_ENTITY_CLASS.getField("name").getAnnotation(InheritedEntityAnnotation.class)).isNull();
        assertThat(USER_INFO_ENTITY_CLASS.getField("name").getAnnotation(UserInfoEntityAnnotation.class)).isNotNull();
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("age").getAnnotation(EntityAnnotation.class)).isNull();
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("age").getAnnotation(InheritedEntityAnnotation.class)).isNull();
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("age").getAnnotation(UserInfoEntityAnnotation.class)).isNotNull();
    }

    @Test
    public void testIdFieldGetDeclaredAnnotations() throws NoSuchFieldException {
        Collection<Class<? extends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getField("id").getDeclaredAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
        List<Class<? extends Annotation>> expectedAnnotationList = Arrays.asList(EntityAnnotation.class, InheritedEntityAnnotation.class);
        assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
        assertThat(annotationList).containsAll(expectedAnnotationList);
    }

    @Test
    public void testNameFieldGetDeclaredAnnotations() throws NoSuchFieldException {
        Collection<Class<? extends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredField("name").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 testAgeFieldGetDeclaredAnnotations() throws NoSuchFieldException {
        Collection<Class<? extends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredField("age").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 testFieldGetDeclaredAnnotationsByType() throws NoSuchFieldException {
        Collection<Class<? extends Annotation>> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredField("name").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 testFieldGetDeclaredAnnotation() throws NoSuchFieldException {
        assertThat(USER_INFO_ENTITY_CLASS.getField("id").getDeclaredAnnotation(EntityAnnotation.class)).isNotNull();
        assertThat(USER_INFO_ENTITY_CLASS.getField("id").getDeclaredAnnotation(InheritedEntityAnnotation.class)).isNotNull();
        assertThat(USER_INFO_ENTITY_CLASS.getField("id").getDeclaredAnnotation(UserInfoEntityAnnotation.class)).isNull();
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("name").getDeclaredAnnotation(EntityAnnotation.class)).isNull();
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("name").getDeclaredAnnotation(InheritedEntityAnnotation.class)).isNull();
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("name").getDeclaredAnnotation(UserInfoEntityAnnotation.class)).isNotNull();
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("age").getDeclaredAnnotation(EntityAnnotation.class)).isNull();
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("age").getDeclaredAnnotation(InheritedEntityAnnotation.class)).isNull();
        assertThat(USER_INFO_ENTITY_CLASS.getDeclaredField("age").getDeclaredAnnotation(UserInfoEntityAnnotation.class)).isNotNull();
    }
}

单元测试方法介绍:

testGetDeclaringClass 使用getDeclaringClass方法获取到字段所在类(声明类)的Class对象

testGetType 使用getType方法获取字段的类型

testGetName 使用getName方法获取字段的名称

testGetModifiers 使用getModifiers获取修饰符,并使用Modifier类提供的静态方法依次判断了是否使用了public、private、protected等修饰符

testGetFieldValue 使用get方法获取对象中字段的值,如果字段不可访问会抛出IllegalAccessException异常,使用setAccessible方法可以控制访问权限。

testSetFieldValue 使用set方法设置对象中字段的值,如果字段不可访问会抛出IllegalAccessException异常,使用setAccessible方法可以控制访问权限。

testIdFieldGetAnnotations 使用getAnnotations获取字段的所有注解

testNameFieldGetAnnotations 使用getAnnotations获取字段的所有注解

testAgeFieldGetAnnotations 使用getAnnotations获取字段的所有注解

testFieldGetAnnotationsByType 使用getAnnotationsByType从字段的注解中获取指定类型的注解

testFieldGetAnnotation 使用getAnnotation从字段的注解中获取指定类型的注解

testIdFieldGetDeclaredAnnotations 使用getDeclaredAnnotations获取字段的所有注解

testNameFieldGetDeclaredAnnotations 使用getDeclaredAnnotations获取字段的所有注解

testAgeFieldGetDeclaredAnnotations 使用getDeclaredAnnotations获取字段的所有注解

testFieldGetDeclaredAnnotationsByType 使用getDeclaredAnnotationsByType从字段的注解中获取指定类型的注解

testFieldGetDeclaredAnnotation 使用getDeclaredAnnotation从字段的注解中获取指定类型的注解

相关推荐
华科易迅5 分钟前
MybatisPlus增删改查操作
android·java·数据库
standovon34 分钟前
Spring Boot整合Redisson的两种方式
java·spring boot·后端
IAUTOMOBILE1 小时前
Python 流程控制与函数定义:从调试现场到工程实践
java·前端·python
hutengyi1 小时前
PostgreSQL版本选择
java
皮皮林5511 小时前
重磅!JetBrains 正式发布全新的 AI 开发工具,定名 AI IDE AIR
java·intellij idea
MX_93591 小时前
SpringMVC请求参数
java·后端·spring·servlet·apache
ID_180079054732 小时前
小红书笔记评论 API,Python 调用示例与完整 JSON 返回参考
java·开发语言
lifewange2 小时前
java连接Mysql数据库
java·数据库·mysql
云原生指北2 小时前
命令行四件套:fd-rg-fzf-bat
java·大数据·elasticsearch
人间打气筒(Ada)3 小时前
go实战案例:如何通过 Service Meh 实现熔断和限流
java·开发语言·golang·web·istio·service mesh·熔断限流