简体   繁体   中英

Is this annotation on the array or on the element type the array?

Look at this simple code.

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

We know that @Bar is annotating Baz , and @Foo is annotating Stream (I've written a similar example here, compile it online! ).

But what about this code?

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

Here we have a String[] annotated with @Foo (whatever the annotation is, it's not important for this question).

My question is, is @Foo annotated on String or String[] ?

It's quite important to determine the target of the annotation, since sometimes we use annotations like @NotNull to represent nullabilities of a type, and @NotNull List<String> means a list which is never null is containing some possibly null strings; List<@NotNull String> represents a list which is possibly null but the members are never null.

A possible use case: I need a @NotNull to show args is not null and another @NotNull to show the members of args are also not null? I need to annotate them both at the same time. If args is a java.util.List , I can use @NotNull List<@NotNull String> . But args is an array -- and I don't know how does the annotation affect on the type of args .

Defining @NonNull before the array level seems to do the trick (for the Checker Framework at least):

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
    }
}

Results in two errors (cf. live demo ):

| 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                                    |      |        |

To answer your actual question, see the specification, §9.7.4 :

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

@A applies to the array type int[][] , @B applies to its component type int[] , and @C applies to the element type int .

So @Foo String[] args is actually annotating String (read as: a possibly null array of non-null strings).

There are two possible answers to the question "in @Foo String[] args , what is @Foo annotating?".

  • If @Foo is a type annotation (that is, the definition of Foo is meta-annotated with @Target(ElementType.TYPE_USE) ), then @Foo applies to the element type String , and you have declared an array of @Foo String .

  • If Foo is a declaration annotation (its definition is not meta-annotated with @Target(ElementType.TYPE_USE) ), then @Foo applies to the entire declaration String[] args . This is uncommon for formal paremeters.

In that position, the @Foo annotation cannot refer to the array type String[] .

(The other response gives a useful answer for @NonNull in particular, but doesn't answer the original question.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM