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

相关推荐
hashiqimiya1 小时前
android studio中修改java逻辑对应配置的xml文件
xml·java·android studio
liuzhenghua662 小时前
Python任务调度模型
java·运维·python
結城2 小时前
mybatisX的使用,简化springboot的开发,不用再写entity、mapper以及service了!
java·spring boot·后端
小前端大牛马2 小时前
java教程笔记(十一)-泛型
java·笔记·python
东阳马生架构2 小时前
商品中心—2.商品生命周期和状态的技术文档
java
星辰离彬2 小时前
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
java·spring boot·后端·sql·mysql·性能优化
q_19132846952 小时前
基于Springboot+Vue的办公管理系统
java·vue.js·spring boot·后端·intellij idea
什么半岛铁盒3 小时前
Linux线程与进程关系及底层实现
java·linux·运维
2301_794333913 小时前
Maven 概述、安装、配置、仓库、私服详解
java·开发语言·jvm·开源·maven