【反射】Field类

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

一、准备工作

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

二、获取Field对象

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

GetFieldInstanceTests类:

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 USER_INFO_ENTITY_CLASS = UserInfoEntity.class;

    @Test
    public void testGetFields() {
        // getFields 获取当前类及其父类中使用public定义的字段
        Collection fieldNameList = Arrays.stream(USER_INFO_ENTITY_CLASS.getFields()).map(Field::getName).collect(Collectors.toList());
        List 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 declaredFieldNameList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredFields()).map(Field::getName).collect(Collectors.toList());
        List 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类:

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 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> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getField("id").getAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
        List> expectedAnnotationList = Arrays.asList(EntityAnnotation.class, InheritedEntityAnnotation.class);
        assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
        assertThat(annotationList).containsAll(expectedAnnotationList);
    }

    @Test
    public void testNameFieldGetAnnotations() throws NoSuchFieldException {
        Collection> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getField("name").getAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
        List> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
        assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
        assertThat(annotationList).containsAll(expectedAnnotationList);
    }

    @Test
    public void testAgeFieldGetAnnotations() throws NoSuchFieldException {
        Collection> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredField("age").getAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
        List> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
        assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
        assertThat(annotationList).containsAll(expectedAnnotationList);
    }

    @Test
    public void testFieldGetAnnotationsByType() throws NoSuchFieldException {
        Collection> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getField("name").getAnnotationsByType(UserInfoEntityAnnotation.class)).map(Annotation::annotationType).collect(Collectors.toList());
        List> 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> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getField("id").getDeclaredAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
        List> expectedAnnotationList = Arrays.asList(EntityAnnotation.class, InheritedEntityAnnotation.class);
        assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
        assertThat(annotationList).containsAll(expectedAnnotationList);
    }

    @Test
    public void testNameFieldGetDeclaredAnnotations() throws NoSuchFieldException {
        Collection> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredField("name").getDeclaredAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
        List> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
        assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
        assertThat(annotationList).containsAll(expectedAnnotationList);
    }

    @Test
    public void testAgeFieldGetDeclaredAnnotations() throws NoSuchFieldException {
        Collection> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredField("age").getDeclaredAnnotations()).map(Annotation::annotationType).collect(Collectors.toList());
        List> expectedAnnotationList = Arrays.asList(UserInfoEntityAnnotation.class);
        assertThat(annotationList.size()).isEqualTo(expectedAnnotationList.size());
        assertThat(annotationList).containsAll(expectedAnnotationList);
    }

    @Test
    public void testFieldGetDeclaredAnnotationsByType() throws NoSuchFieldException {
        Collection> annotationList = Arrays.stream(USER_INFO_ENTITY_CLASS.getDeclaredField("name").getDeclaredAnnotationsByType(UserInfoEntityAnnotation.class)).map(Annotation::annotationType).collect(Collectors.toList());
        List> 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从字段的注解中获取指定类型的注解

你可能感兴趣的:(#,反射,java反射,java)