首页 > 解决方案 > 这个注释是在数组上还是在数组的元素类型上?

问题描述

看看这个简单的代码。

try (@Foo Stream<@Bar Baz> foo = blabla) { }

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

但是这段代码呢?

void whatever(@Foo String[] args) { }

这里我们有一个String[]注解@Foo(不管注解是什么,对这个问题都不重要)。

我的问题是,是否在or上进行@Foo了注释?StringString[]

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

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

标签: javaannotations

解决方案


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

import org.checkerframework.checker.nullness.qual.NonNull;

class App {
    void foo() {
        String @NonNull [] bar;
        bar = null; // NOK
        bar = new String[1];
        bar[0] = null; // NOK
    }
}

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

| No. | Type  |                                 Description                                 | Line | Column |
|-----|-------|-----------------------------------------------------------------------------|------|--------|
|   1 | error | Error: [assignment.type.incompatible] incompatible types in assignment.     |    6 |     15 |
|     |       |   found   : null                                                            |      |        |
|     |       |   required: @Initialized @NonNull String @UnknownInitialization @NonNull [] |      |        |
|   2 | error | Error: [assignment.type.incompatible] incompatible types in assignment.     |    8 |     18 |
|     |       |   found   : null                                                            |      |        |
|     |       |   required: @Initialized @NonNull String                                    |      |        |

要回答您的实际问题,请参阅规范 §9.7.4

@C int @A [] @B [] f;

@A适用于数组类型int[][]@B适用于其组件类型 int[],并@C适用于元素类型int

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


推荐阅读