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