如何反射访问记录组件的泛型类型参数注解?
Record组件无法通过反射获取类型参数的注解
问题现象
在Java代码中尝试通过反射访问类型参数上的@Annot注解时,普通类的字段可以正常获取注解,但Record组件的类型参数注解无法被读取。运行测试代码后输出如下:
[@tmp.Test$Annot()] []
反编译代码显示出明显差异:
普通类的字段定义完整保留了类型参数的注解:
public static final class C { List<@Test.Annot String> strings; public C() {} }
而Record的组件定义中,类型参数的注解仅出现在构造方法参数和访问方法里,组件本身的类型定义丢失了注解信息:
public static record R(List<String> strings) { public R(List<@Test.Annot String> strings) { this.strings = strings; } public List<@Test.Annot String> strings() { return this.strings; } }
完整测试代码:
public final class Test { @Target({ElementType.TYPE_USE, ElementType.RECORD_COMPONENT}) @Retention(RetentionPolicy.RUNTIME) public @interface Annot {} public static final class C { List<@Annot String> strings; } public record R(List<@Annot String> strings) {} public static void main(String[] args) { { Field field = C.class.getDeclaredFields()[0]; AnnotatedParameterizedType type = (AnnotatedParameterizedType) field.getAnnotatedType(); AnnotatedType argument = type.getAnnotatedActualTypeArguments()[0]; System.out.println(Arrays.toString(argument.getAnnotations())); } { RecordComponent component = R.class.getRecordComponents()[0]; AnnotatedParameterizedType type = (AnnotatedParameterizedType) component.getAnnotatedType(); AnnotatedType argument = type.getAnnotatedActualTypeArguments()[0]; System.out.println(Arrays.toString(argument.getAnnotations())); } } }
临时解决方法
如果在Record组件的容器类型(比如示例中的List)上添加@Annot注解,修改后的Record定义如下:
public record R(@Annot List<@Annot String> strings) {}
反编译后会发现Record组件的类型参数注解被正确保留:
public static record R(@Test.Annot List<@Test.Annot String> strings) ...
此时通过反射可以同时获取到List本身和其类型参数String上的@Annot注解。
根本原因
这是JDK的已知Bug(编号JDK-8292159),问题在于编译器没有将Record组件类型参数的注解正确保留到RecordComponent的元数据中,只有当组件本身带有注解时,类型参数的注解才会被同步保留。
内容的提问来源于stack exchange,提问作者Alex R
相关产品推荐
相关产品推荐

