@Repeatable允许同一位置多次声明同类型注解,需配套定义容器注解(含value()返回该注解数组),且@Target与@Retention必须一致;运行时须用getAnnotationsByType()获取全部实例。

@Repeatable 元注解让同一个类或方法上可以多次使用同一个自定义注解,解决传统注解“只能出现一次”的限制,是 Java 8 引入的重要增强特性。
为什么需要 @Repeatable?
在 Java 8 之前,若想为一个元素标注多个同类语义的元数据(比如多个权限、多个验证规则、多个事件监听器),只能靠“容器注解”——即额外定义一个数组类型的包装注解。这种方式冗余且不直观。
有了 @Repeatable,开发者可直接重复写同一注解,语义更清晰,代码更简洁。
如何正确声明可重复注解?
必须满足两个条件:
- 目标注解需用 @Repeatable 修饰,并指定其“容器注解”类型(该类型必须是注解,且值属性为对应注解类型的数组)
- 容器注解的 value() 方法返回值必须是该重复注解类型的数组
例如:定义 @Role 注解后,需配套定义 @Roles(容器),并在 @Role 上标注 @Repeatable(Roles.class)。
编译器和运行时如何处理?
Java 编译器会自动将多个重复注解“打包”进容器注解中。你通过反射获取时:
- 调用 getAnnotation(RepeatedAnnotation.class) → 返回 null(单个实例不存在)
- 调用 getAnnotation(ContainerAnnotation.class) → 返回容器实例,再取 value() 得到注解数组
- 更推荐用 getAnnotationsByType(RepeatedAnnotation.class) → 直接返回所有重复注解实例,无需手动解包
常见误用与注意事项
@Repeatable 不是万能的:
- 不能用于 JDK 自带的标准注解(如 @Override、@Deprecated),它们未声明为可重复
- 容器注解的 target、retention 必须与重复注解兼容(通常保持一致)
- 重复注解之间无顺序保证,不要依赖声明顺序做逻辑判断
- IDE 和部分框架(如 Spring)已支持,但老旧工具链可能识别异常,建议统一升级 JDK 8+ 环境

















