这个注释是在数组上还是在元素类型数组上?

ice*_*000 2 java annotations

看看这个简单的代码。

\n\n
try (@Foo Stream<@Bar Baz> foo = blabla) { }\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们知道这@Bar是注释Baz,并且@Foo是注释Stream(我在这里写了一个类似的例子,在线编译它!)。

\n\n

但是这段代码呢?

\n\n
void whatever(@Foo String[] args) { }\n
Run Code Online (Sandbox Code Playgroud)\n\n

这里我们有一个String[]注释@Foo(无论注释是什么,对于这个问题来说并不重要)。

\n\n

我的问题是,注释@FooString或 上String[]

\n\n

确定注释的目标非常重要,因为有时我们使用注释来@NotNull表示类型的可为空性,并且@NotNull List<String>意味着永远不为空的列表包含一些可能为空的字符串;List<@NotNull String>表示一个可能为空但成员永远不为空的列表。

\n\n

一个可能的用例:我需要一个@NotNull来显示args不为空,另一个@NotNull来显示 的成员args也不为空?我需要同时注释它们。如果args是a java.util.List,我可以使用@NotNull List<@NotNull String>。Butargs是一个数组——我不知道注释如何影响args.

\n

Mar*_*vin 7

在数组级别之前定义@NonNull似乎可以解决问题(至少对于 Checker 框架而言):

\n\n
import org.checkerframework.checker.nullness.qual.NonNull;\n\nclass App {\n    void foo() {\n        String @NonNull [] bar;\n        bar = null; // NOK\n        bar = new String[1];\n        bar[0] = null; // NOK\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

导致两个错误(参见现场演示):

\n\n
| No. | Type  |                                 Description                                 | Line | Column |\n|-----|-------|-----------------------------------------------------------------------------|------|--------|\n|   1 | error | Error: [assignment.type.incompatible] incompatible types in assignment.     |    6 |     15 |\n|     |       |   found   : null                                                            |      |        |\n|     |       |   required: @Initialized @NonNull String @UnknownInitialization @NonNull [] |      |        |\n|   2 | error | Error: [assignment.type.incompatible] incompatible types in assignment.     |    8 |     18 |\n|     |       |   found   : null                                                            |      |        |\n|     |       |   required: @Initialized @NonNull String                                    |      |        |\n
Run Code Online (Sandbox Code Playgroud)\n\n

要回答您的实际问题,请参阅规范 \xc2\xa79.7.4

\n\n
\n
@C int @A [] @B [] f;\n
Run Code Online (Sandbox Code Playgroud)\n\n

@A适用于数组类型int[][]@B适用于其组件类型\n int[]以及@C适用于元素类型int

\n
\n\n

实际上@Foo String[] args是注释String(读作:非空字符串的可能为空数组)。

\n


mer*_*nst 5

@Foo String[] args对于“什么是注释?”这个问题有两种可能的答案@Foo

  • 如果@Foo类型注释(即 的定义Foo是用 进行元注释的@Target(ElementType.TYPE_USE)),则@Foo适用于元素类型String,并且您已经声明了 的数组@Foo String

  • 如果Foo声明注释(其定义未使用 元注释@Target(ElementType.TYPE_USE)),则@Foo适用于整个声明String[] args。这对于形式参数来说并不常见。

在该位置,@Foo注释不能引用数组类型String[]

(另一个答案给出了特别有用的答案@NonNull,但没有回答原来的问题。)