3

I am unable to retrieve the annotation at the left of the square brackets of an array:

public static @MyNullable1 String @MyNullable2[] array = null;

@Test
public void test() throws Exception {
    Annotation[] annotations = getClass().getField("array").getAnnotations();
    System.out.println(Arrays.toString(annotations));
}

The result is only:

[@test.MyNullable1()]

And, if I remove the @MyNullable2, IDEA reports 'null' is assigned to a variable that is annotated with @NotNull: enter image description here

Why is IDEA reporting this? How can I get the annotation at the left of the square brackets? And what's different in annotations at different positions?

Here are MyNullable1 and MyNullable2:

@Documented
@Nonnull(when = When.MAYBE)
@Retention(RetentionPolicy.RUNTIME)
@TypeQualifierNickname
@Target({
    ElementType.METHOD,
    ElementType.FIELD,
    ElementType.PARAMETER,
    ElementType.LOCAL_VARIABLE,
    ElementType.TYPE_USE,
})
public @interface MyNullable1 {}
@Documented
@Nonnull(when = When.MAYBE)
@Retention(RetentionPolicy.RUNTIME)
@TypeQualifierNickname
@Target({
    ElementType.METHOD,
    ElementType.FIELD,
    ElementType.PARAMETER,
    ElementType.LOCAL_VARIABLE,
    ElementType.TYPE_USE,
})
public @interface MyNullable2 {}

1 Answer 1

4

As you have found out, @MyNullable1 annotates the field array, but it also annotates the array's component type, String. On the other hand, @MyNullable2 does not annotate the field array, but it does annotate the type of the field, String[]. This is the effect that the different annotation positions have.

You should use getAnnotatedType to get the annotations on the type. Here is some code that finds both @MyNullable1 (annotating String) and @MyNullable2 (annotating String[]).

var type = getClass().getField("array").getAnnotatedType();
// this prints @mypackage.MyNullable1() java.lang.String @mypackage.MyNullable2()[]
// so both annotations you want are in this
System.out.println(type); //

// this does not print null, showing that MyNullable2 is annotating 'String[]'
System.out.println(type.getAnnotation(MyNullable2.class));

// I *know* the type of the field, so this cast always succeeds.
// You should add an instanceof check if you are working with an unknown field, of course
var arrayComponentType = ((AnnotatedArrayType)type).getAnnotatedGenericComponentType();
// this does not print null, showing that MyNullable1 is annotating the array component type 'String'
System.out.println(arrayComponentType.getAnnotation(MyNullable1.class));
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.