@RecentlyNonNull注解是什么?

58

我正在Android Studio上进行代码检查,出现以下警告:

Probable bugs
@NotNull/@Nullable problems 
Not annotated method overrides method annotated with @RecentlyNonNull

以下代码:

@Override
public String toString() {
    return title;
}

输入图像描述这里

我之前见过@NonNull注释,它意味着返回值永远不会为null,但是@RecentlyNonNull又是什么呢?我应该在什么时候使用它呢?

通过谷歌搜索,我们找到了https://android.googlesource.com/platform/tools/metalava/+/fcb3d99ad3fe17a266d066b28ceb6c526f7aa415/stub-annotations/src/main/java/android/support/annotation/RecentlyNonNull.java

但是这个网页并没有提供任何解释。

Lint建议添加此注释,但它的作用是什么呢?

输入图像描述这里


1
https://android.googlesource.com/platform/tools/metalava/+/master/stub-annotations/ - AskNilesh
4
如果这是一个私有注释,Android Studio 不应将其作为修复选项提供。 - Csaba Toth
2个回答

46
考虑将@RecentlyNonNull视为@NonNull约束,并在代码中以相同的方式尊重它,因为@RecentlyNonNull本质上是一个@NonNull约束。这意味着在实际问题中,OP应该使用@NonNull注释覆盖的方法,以符合在超类中定义的@NonNull(在构建时转换为@RecentlyNonNull)。

@RecentlyNonNull注释不属于SDK javadoc API的一部分。
不在support子包中,因为它不是设计成出现在源代码中的。相反,它在构建时计算并替换@NonNull,如果在存根源文件中被认为是“最近的”。

由于这是内部处理,我没有简单明了的答案,但我可以给你一些指针来更好地理解这个注释及其起源。

1)@RecentlyNonNull或@RecentlyNullable:只在存根源文件中生成的注释。

在Android中,生成的存根文件和生成的文档存根没有带来相同级别的信息:@RecentlyNonNull@RecentlyNullable可能出现在存根文件中,但从不出现在仅依赖存根文件的文档存根中。

您可以在Options类源代码中找到这些信息:

"$ARG_DOC_STUBS ", "为API生成文档存根源文件。文档存根文件类似于常规存根文件,但有一些区别。例如,在存根文件中,我们将使用特殊注释(如@RecentlyNonNull)而不是@NonNull来指示元素最近被标记为非null,而在文档存根中,我们将仅列出此项作为@NonNull...。
这个googlesource document证实了这一点:
引用: 这里有一些注释不在支持库中,比如@RecentlyNullable和@RecentlyNonNull。这些仅用于存根,自动标记代码为最近注释的空/非空。我们不希望这些注释出现在源代码中;最近性是在构建时计算并注入到存根中代替正常的空注释。
2)为代码linter和IDE警告/错误引入的注释。
根据这个blog,这些注释起源于Kotlin支持,并允许编译器/ linter根据非null约束的最近程度应用严重性级别(最近:警告编译,不是最近:错误编译)。
通常,在Kotlin中,nullability合约违规会导致编译错误。但是为了确保新注释的API与您现有的代码兼容,我们正在使用由Kotlin编译器团队提供的内部机制将API标记为最近注释过的。最近注释过的API仅会从Kotlin编译器产生警告而不是错误。您需要使用Kotlin 1.2.60或更高版本。
我们的计划是仅在新添加的nullability注释中产生警告,并在以下年度的Android SDK中将其严重级别提高到错误。目标是为您提供充足的时间来更新您的代码。

2
那么我应该把RecentlyNonNull视为可以为空的东西,还是不能为空的东西? - android developer
3
你应该考虑到,使用注解的参数、字段或方法返回值被设计为不为空,类似于 @NonNull 的作用(https://dev59.com/8FsV5IYBdhLWcg3w8imr),但这个约束是“最近”添加的。因此,代码检查工具可能会更加宽容(当然你可以修改它)。 - davidxxx
1
那么我可以假设它不是空的,对吗? - android developer
2
你确实应该。 - davidxxx
1
它只是用于库,对吧?不用于Android框架。是这样的吗?我问这个问题是因为有一个视频提到了关于Android的新内容:https://youtu.be/fnkFOhA7FC4?list=PLWz5rJ2EKKc9hqKx4qZWolQxy59Bt20t_&t=919,但是这很奇怪,因为它根本不是新的…… - android developer
实际上,FusedLocationProviderClient.getLastLocation()被标记为@RecentlyNonNull,但在实践中它可能返回null。 - Pavel Poley

0

显然,它意味着非空性,但我猜“最近”的部分意味着它只是最近被注释为这样。

例如,Object.toString 以前不是 @NonNull,所以现在它是,我们说它是 @RecentlyNonNull,谁重写它也应该是 @NonNull。 如果你查看源代码,注释是不存在的。这意味着某些魔法使得这个特定的方法不可为空,并且这就是为什么它被标记为“最近”的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接