Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 913
ice1000 Avatar asked Jun 04 '26 13:06

ice1000


1 Answers

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

like image 140
Marvin Avatar answered Jun 07 '26 23:06

Marvin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!