更换METHOD / FIELD / etc的兼容性风险是什么。 TYPE_USE

问题描述 投票:0回答:1

我有一个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

java java-8 annotations compatibility
1个回答
1
投票

此更改过程中可能会出现许多源兼容性问题:

  • 返回类型为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();
  • 这样的更改使Kotlin代码中的注释的所有用法无效。在Kotlin中,TYPE_USE注释与其他注释之间存在严格的语法差异。例如。必须将PARAMETER注释用作fun(@MyAnnotation param : String) {...}。这对于TYPE_USE注释是不正确的,它必须用作fun(param : @MyAnnotation String) {...}。如果您的客户使用Kotlin,则必须修复每一个注释使用。
  • 此类更改不允许在Groovy代码中使用注释。当前,正如[C​​0]所说,Groovy不支持Java 8中引入的TYPE_PARAMETER和TYPE_USE元素类型。如果您的客户使用Groovy,他们将无法再使用您的注释包。

尽管在运行时不会出现问题。由于注释的保留策略是Groovy documentation(不是CLASS),而注释存在于类文件中,因此运行时将忽略它们。完全没有必要将注释包添加到类路径中。

© www.soinside.com 2019 - 2024. All rights reserved.