我有一个Java包,其中包含外部客户端使用的注释。该软件包出现在Java 8之前,因此从历史上看,这些注释的目标是ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE
。现在,该软件包至少需要Java 8版本。语义上,包装中的注释适用于这些类型,例如注释方法时,注释有效地应用于方法返回类型。现在,客户也希望对通用类型参数进行注释(例如List<@MyAnnotation String>
)。由于我们放弃了对Java 7及更低版本的支持,因此将注释目标设置为ElementType.TYPE_USE
,并为减少歧义,删除现有目标,这似乎是很自然的。
这里是问题:用ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE
替换TYPE_USE
目标时,现有客户端是否存在兼容性风险?现有代码是否有可能停止编译?二进制兼容性如何?如果在运行时将更改之前编译的类文件与较新的注释包一起使用,是否会引起任何运行时问题?
如果这很重要,注释的保留策略为CLASS
。
此更改过程中可能会出现许多源兼容性问题:
void
的方法无法再注释。 @MyAnnotation void method() {}
可以与ElementType.METHOD
目标一起编译,但不能与TYPE_USE
目标一起编译。TYPE_USE
注释必须出现在限定符之后。例如。 void method(@MyAnnotation OuterClass.InnerClass param) {}
是具有ElementType.PARAMETER
目标的有效代码,但在更改为void method(OuterClass.@MyAnnotation InnerClass param) {}
后应更新为TYPE_USE
。@MyAnnotation String[] getData();
之前对方法getData
进行注释,因此注释客户端可能会假定注释已应用于返回类型(字符串数组)。迁移后,相同的代码意味着注释将应用于数组组件(字符串)。这可能会导致行为更改,具体取决于注释的语义以及客户端如何对其进行处理。为了保留含义,客户应将这样的代码更新为String @MyAnnotation [] getData();
。TYPE_USE
注释与其他注释之间存在严格的语法差异。例如。必须将PARAMETER
注释用作fun(@MyAnnotation param : String) {...}
。这对于TYPE_USE
注释是不正确的,它必须用作fun(param : @MyAnnotation String) {...}
。如果您的客户使用Kotlin,则必须修复每一个注释使用。尽管在运行时不会出现问题。由于注释的保留策略是Groovy documentation(不是CLASS
),而注释存在于类文件中,因此运行时将忽略它们。完全没有必要将注释包添加到类路径中。