javaspringspring-bootfully-qualified-namingjakarta-validation

"Annotation not applicable to this kind of reference" error for Valid annotation with class name with the package


This code is working:

public class Foo {

    private List<@Valid String> bar = Collections.emptyList();
}

But this one is not:

public class Foo {

    private List<@Valid java.lang.String> bar = Collections.emptyList();
}

The error message in my IDE is:

Annotation not applicable to this kind of reference

also I've noticed that import to List becomes unused:

enter image description here


Solution

  • This would be covered under the "Where Annotations May Appear" chapter in the Java Language Specification, see here.

    The chapter states

    A type annotation is admissible if both of the following are true:

    • The simple name to which the annotation is closest is classified as a TypeName, not a PackageName.
    • If the simple name to which the annotation is closest is followed by "." and another TypeName - that is, the annotation appears as @Foo T.U - then U denotes an inner class of T.

    and later goes on to say

    It is a compile-time error if an annotation of interface A applies to a type (or any part of a type) in a type context, and A is applicable in type contexts, but the annotation is not admissible.

    and gives an example that is equivalent to yours

    For example, assume an annotation interface TA which is meta-annotated with just @Target(ElementType.TYPE_USE). The terms @TA java.lang.Object and java.@TA lang.Object are illegal because the simple name to which @TA is closest is classified as a package name. On the other hand, java.lang.@TA Object is legal.

    So you could move the annotation to after the package name prefix and it would compile (so you could continue using a fully qualified name, if it was necessary to do so)

    private List<java.lang.@Valid Integer> bar = Collections.emptyList();
    

    Here's another example, simply to highlight this isn't strictly related to your use of the annotation on a type used as a generic type argument (if that was a concern)

    @Target(value = ElementType.TYPE_USE)
    @interface ExampleAnnotation {} // similar to @Valid
    class OkExample extends @ExampleAnnotation Observable {
        @ExampleAnnotation public static String ok;
        @ExampleAnnotation public static java.lang.String bad; // same error
    }
    class BadExample extends @ExampleAnnotation java.util.Observable {} // same error