【反射】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从字段的注解中获取指定类型的注解

相关推荐
Yvemil713 分钟前
《开启微服务之旅:Spring Boot 从入门到实践》(三)
java
Anna。。14 分钟前
Java入门2-idea 第五章:IO流(java.io包中)
java·开发语言·intellij-idea
.生产的驴36 分钟前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
爱上语文38 分钟前
宠物管理系统:Dao层
java·开发语言·宠物
王ASC1 小时前
SpringMVC的URL组成,以及URI中对/斜杠的处理,解决IllegalStateException: Ambiguous mapping
java·mvc·springboot·web
是小崔啊1 小时前
开源轮子 - Apache Common
java·开源·apache
因我你好久不见1 小时前
springboot java ffmpeg 视频压缩、提取视频帧图片、获取视频分辨率
java·spring boot·ffmpeg
程序员shen1616111 小时前
抖音短视频saas矩阵源码系统开发所需掌握的技术
java·前端·数据库·python·算法
Ling_suu2 小时前
SpringBoot3——Web开发
java·服务器·前端
天使day2 小时前
SpringMVC
java·spring·java-ee