Field.getAnnotation()只能获取@Retention(RUNTIME)且@Target(FIELD)的注解;标准校验/映射注解如@NotNull、@Column默认满足,自定义注解需显式声明;读取前须setAccessible(true),父类字段需向上遍历。

Java中Field.getAnnotation()可以直接读取字段上声明的注解,但要注意:它只返回**运行时保留(@Retention(RetentionPolicy.RUNTIME))**且**作用在字段上(@Target(ElementType.FIELD))**的注解。校验注解(如@NotNull、@Size)和映射注解(如@Column、@JsonProperty)大多满足这两个条件,所以通常能正常获取。
确认注解是否支持运行时读取
很多标准注解(如Hibernate的@Column、Jackson的@JsonProperty、Jakarta Bean Validation的@NotNull)默认就是RetentionPolicy.RUNTIME,可直接用getAnnotation()。但自定义注解必须显式声明:
- 检查注解定义里是否有
@Retention(RetentionPolicy.RUNTIME) - 确认
@Target包含ElementType.FIELD(例如@Target({ElementType.FIELD, ElementType.METHOD})) - 如果注解是
CLASS或SOURCE级别,反射无法获取
基本读取方式(单个注解)
通过Class.getDeclaredField()拿到Field对象,再调用getAnnotation(Class<T>):
Person person = new Person();
Field field = Person.class.getDeclaredField("name");
field.setAccessible(true); // 忽略private访问限制
// 读取@NotNull(来自jakarta.validation.constraints)
NotNull notNull = field.getAnnotation(NotNull.class);
if (notNull != null) {
System.out.println("该字段不能为空");
}
// 读取@Column(来自jakarta.persistence)
Column column = field.getAnnotation(Column.class);
if (column != null) {
System.out.println("数据库列名:" + column.name());
}
批量读取多个校验/映射注解
一个字段可能同时有多个注解(比如@NotNull + @Size(max=50) + @Column(name="user_name")),可以分别调用getAnnotation(),或使用getAnnotations()获取全部:
立即学习“Java免费学习笔记(深入)”;
-
field.getAnnotations()返回所有运行时注解数组,需遍历判断类型 - 更推荐按需调用
getAnnotation(Class),语义清晰、避免类型转换错误 - 注意:
@Valid等容器类注解不直接作用于字段,而是触发嵌套校验,不能用getAnnotation()直接读取其约束规则
常见问题与注意事项
实际使用中容易踩坑的地方:
-
getDeclaredField()只能获取本类声明的字段,父类字段需用getSuperclass()向上遍历 - 私有字段必须先调用
setAccessible(true),否则抛IllegalAccessException - 泛型字段(如
List<String>)上的注解仍可读取,但类型信息需结合getGenericType()解析 - Spring的
@Value、MyBatis的@Param等方法级注解不能在字段上使用,自然也无法读取


















