javaannotations

Java: How to prevent non-top level annotations on type?


Java: How to prevent non-top level annotations on type? e.g.,

@Target(value={ElementType.TYPE})
@Retention(value=RetentionPolicy.RUNTIME)
public @interface FooList {
    public Foo[] value();
}


@Retention(value=RetentionPolicy.RUNTIME)
public @interface Foo {
    public String name();
}

@FooList({
     @Foo(name="ABC"),
     @Foo(name="XyZ")
})
@Foo(name="EFG")   // no compile error here
public class Bar {
}

@Foo should be inside @FooList only. But no compile error when @Foo is annotated on type Bar directly.


Solution

  • What does it mean when @Target is not present?

    From the documentation of @Target:

    If an @Target meta-annotation is not present on an annotation interface T, then an annotation of type T may be written as a modifier for any declaration.

    And from §9.6.4.1 - Target of the Java Language Specification:

    If an annotation of type java.lang.annotation.Target is not present on the declaration of an annotation interface A, then A is applicable in all declaration contexts and in no type contexts.

    How to define an annotation that's not applicable in any context?

    From the documentation of @Target:

    This @Target meta-annotation indicates that the declared class or interface is intended solely for use as a member class or interface in complex annotation interface declarations. It cannot be used to annotate anything directly:

    @Target({})
    public @interface MemberInterface {
        ...
    }
    

    In short, meta-annotate your @Foo annotation with @Target({}).