Skip to content

JEP 120: Repeating Annotations | 重复的注解

摘要

改变 Java 编程语言,允许将相同类型的注解多次应用于单个程序元素。

目标

提高源代码的可读性,以便将多个相同注解类型的逻辑应用于给定的程序元素。

动机

在 EE 和其他地方,经常使用的注解编程惯用语笨拙地使用容器注解来模拟应用多个注解的能力。内置对重复注解的支持将提高源代码的可读性。

描述

实现这个语言特性的基本方法是将基础类型的重复注解糖化成一个单独的容器注解;容器注解具有一个 values 方法,返回基础注解类型的数组。要为特定的注解类型启用重复注解,基础注解类型的声明将需要包括一个新的 meta-annotation ,比如 @ContainerAnnotation ,用于声明哪个其他注解类型应被用作容器。如果容器与基础注解不兼容,包括保留策略或目标上的问题差异,应发出警告和错误。

开放的设计问题包括是否支持多层编译器生成的容器。例如,如何处理以下代码:

java
@A(1)
@A(2)
@AContainer
@AContainerContainer
foo();

逻辑上等同于

java
@AContainerContainer(@AContainer({@A(1), @A2}), @AContainer)
foo();

或者在一层嵌套后编译错误:

java
@AContainer({@A(1), @A(2)})
@AContainer
@AContainerContainer
foo();

在库级别上,需要更新平台中反射 API 的实现,包括核心反射和 javax.lang.model ,以处理重复注解信息。例如, AnnotatedElement.getAnnotation(BaseAnnotation.class) 方法将被重新定义,如果基础注解不存在,则会在容器注解中查找。可以向 AnnotatedElement 接口添加一个或多个用于查询注解存在或不存在的方法。如果支持多层编译器生成的嵌套,库的更改将更加广泛。

测试

与所有语言更改一样,需要更新相应的编译器 JCK 测试。

风险和假设

一个风险是这种语言特性与现有库语义之间或与 Java SE 8 中存在的其他语言特性之间可能存在当前未预料到的相互作用。特别是,需要定义重复注解与类型上的注解之间的交互(如果有)。

一个假设是,使用手动容器注解模式的现有 EE 注解类型将迁移到使用重复注解模式,并通过使用验证该特性。

如果各种 Java IDE 在开发过程中不支持这种语言变更,则会减慢特性的实验和设计验证。

依赖

需要定义重复注解与 JEP 104: Java 类型上的注解 之间的交互(如果有)。

影响

  • JDK 的其他组件:预计在 JDK 代码库中直接使用重复注解的情况很少。
  • 兼容性:通常不希望在 JDK 之外拥有实现的接口可能会添加方法。来自 Lambda 项目的默认方法可以帮助限制源代码兼容性的影响。
  • 性能/可扩展性:如果不使用该功能,编译速度不应降低。