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:

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 {}
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));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With