JEP 120:可重复注解
概述
更改 Java 编程语言,以允许对单个程序元素多次应用相同类型的注解。
目标
提高源代码的可读性,在逻辑上将同一注解类型应用于给定程序元素的多个实例。
动机
在 EE 和其他地方带有注解的编程常用习惯用法笨拙地使用容器注解,仅仅是为了模拟应用多个注解的能力。构建对重复注解的支持将提高源代码的可读性。
描述
实现该语言特性的基本方法是将基类型的重复注解**反糖化(desugar)**为单个容器注解;容器注解具有一个 values
方法,该方法返回基注解类型的一个数组。为了使特定注解类型支持重复注解,基注解类型的声明需要包含一个新的元注解,例如 @ContainerAnnotation
,以声明应使用哪种其他注解类型作为容器。如果容器与基注解不兼容,包括保留策略或目标上的问题差异,应该发出警告和错误。
开放的设计问题包括是否支持多层编译器生成的容器。例如,是否应该支持:
@A(1)
@A(2)
@AContainer
@AContainerContainer
foo();
被视作逻辑等价于
@AContainerContainer(@AContainer({@A(1), @A2}), @AContainer)
foo();
或在一级嵌套后出现编译错误导致无法继续。
@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 外部有实现的接口可能会添加方法。来自 Project Lambda 的默认方法可以帮助减少源码兼容性的影响。
- 性能/可扩展性:如果不使用该功能,编译速度应该不会下降。