Meta-Annotations in Java β€” <code>@Retention</code>, <code>@Target</code> and Friends

A meta-annotation is an annotation applied to another annotation. Java's five meta-annotations in java.lang.annotation control where and how long your custom annotations exist, and how they relate to inheritance.

The five meta-annotations

Meta-annotationControls
@RetentionHow long the annotation is kept β€” SOURCE, CLASS, or RUNTIME
@TargetWhich program elements it can be applied to
@InheritedWhether subclasses inherit a class-level annotation
@DocumentedWhether Javadoc includes the annotation
@RepeatableWhether the annotation can appear multiple times on the same element

@Retention β€” three policies

@Retention(RetentionPolicy.SOURCE)     // compiler only, discarded after (@Override, lint)
@Retention(RetentionPolicy.CLASS)      // in bytecode but not loaded by reflection (default)
@Retention(RetentionPolicy.RUNTIME)    // available via reflection β€” most common for frameworks

@Target β€” where the annotation can appear

@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MyAnno { ... }
ElementTypeLocation
TYPEClasses, interfaces, enums, records, annotations
FIELDFields
METHODMethods
PARAMETERMethod / constructor parameters
CONSTRUCTORConstructors
LOCAL_VARIABLELocal variables (rarely useful at runtime)
ANNOTATION_TYPEOther annotations (meta-annotations)
PACKAGEPackage declarations
TYPE_PARAMETERType parameters β€” <@NotNull T>
TYPE_USEAny type use β€” List<@NotNull String>
MODULEModule declarations

@Inherited

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Service {}

@Service
public class BaseService { ... }

public class UserService extends BaseService {}

UserService.class.getAnnotation(Service.class);    // non-null β€” inherited

Only works on class-level annotations. Doesn't affect interfaces or methods.

@Documented

Adds the annotation to the generated Javadoc of the annotated element. Useful for framework annotations that callers need to see in API documentation.

@Repeatable (Java 8+)

@Repeatable(Schedules.class)
public @interface Schedule {
    String dayOfMonth();
    String dayOfWeek() default "*";
}

public @interface Schedules {
    Schedule[] value();                       // "container" annotation
}

@Schedule(dayOfMonth = "1")
@Schedule(dayOfMonth = "15")
public void runTwiceAMonth() { ... }

A realistic template

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimit {
    int permits();
    long periodSeconds();
    boolean perUser() default false;
}

Common mistakes

  • No @Retention β€” defaults to CLASS, so reflection can't see it.
  • No @Target β€” the annotation can be placed anywhere, including useless spots.
  • Using @Inherited on a method annotation β€” it only works on type annotations.
  • Forgetting the container annotation for @Repeatable β€” the compiler tells you, but the error is easy to misread.

Related

Pillar: Java annotations. Siblings: writing custom annotations.