Java 17中RecordComponent为何无法获取Records类上定义的注解信息?
问题结论
这个现象是完全符合Java规范的预期行为,你的预期偏差是对Record组件上的注解传播规则不了解导致的。
核心原因
Java在处理Record组件上的注解时,会根据注解本身的@Target配置,自动将注解传播到对应的生成元素上:
- 如果注解的
@Target包含ElementType.FIELD:注解会被写到生成的私有final成员字段上 - 如果注解的
@Target包含ElementType.METHOD:注解会被写到生成的公共访问器方法上 - 如果注解的
@Target包含ElementType.RECORD_COMPONENT:注解才会被写到RecordComponent元数据中,你通过recordComponents[x].isAnnotationPresent才能读到
你用到的@NotEmpty注解(无论是javax.validation还是jakarta.validation版本),默认的@Target配置通常只包含FIELD、METHOD、PARAMETER、ANNOTATION_TYPE、TYPE_USE,没有包含Java 16才新增的RECORD_COMPONENT类型,所以自然不会被记录到RecordComponent上。
验证示例
你可以用下面的自定义注解做测试,就能看到两边都返回true:
import java.lang.annotation.*; @Target({ElementType.FIELD, ElementType.RECORD_COMPONENT}) @Retention(RetentionPolicy.RUNTIME) @interface TestAnno {} // 定义Record record R(@TestAnno Integer i) {} // 测试代码 public static void main(String[] args) { // 返回true System.out.println(R.class.getRecordComponents()[0].isAnnotationPresent(TestAnno.class)); // 返回true System.out.println(R.class.getDeclaredFields()[0].isAnnotationPresent(TestAnno.class)); }
补充说明
如果你希望@NotEmpty这类校验注解同时能在RecordComponent上被读取到,需要自定义扩展校验注解,给它加上RECORD_COMPONENT的Target配置即可。
内容的提问来源于stack exchange,提问作者Dmitriy Dumanskiy
相关产品推荐
相关产品推荐

