Memra

Meta-annotations: @Retention, @Target, @Documented, @Inherited, @Repeatable

Annotations that annotate annotation declarations — and the critical RUNTIME retention trap.

Meta-annotations

Meta-annotations are annotations applied to annotation declarations themselves. They configure how the annotation is stored, where it can be used, and how it behaves.

@Retention — where the annotation lives

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Audited {}

| Policy | Annotation survives to... | |---|---| | SOURCE | Compile-time only — stripped from .class file. Lombok, @Override | | CLASS | .class file — default if omitted, but not available at runtime | | RUNTIME | JVM at runtime — readable via reflection |

RUNTIME is the only policy that lets reflection read the annotation. Frameworks like Spring and JUnit require RUNTIME; annotation processors (like Lombok) use SOURCE.

@Target — where the annotation can be applied

import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Target({ElementType.METHOD, ElementType.FIELD})
public @interface Validate {}

Common ElementType values: TYPE (class/interface/enum), FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE.

Without @Target, the annotation can be applied to almost any element. With @Target, the compiler enforces the restriction.

@Documented

@Documented
public @interface PublicApi {}

Annotated elements show the annotation in generated Javadoc. Without @Documented, annotations are invisible in the API docs.

@Inherited

@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface Category { String value(); }

If a class is annotated with @Category, its subclasses automatically inherit the annotation. @Inherited applies only to class-level annotations — it has no effect on methods or fields.

@Repeatable

@Repeatable(Tags.class)
public @interface Tag { String value(); }

public @interface Tags { Tag[] value(); }  // container annotation

@Tag("fast")
@Tag("reviewed")
public void process() {}

Without @Repeatable, applying the same annotation twice is a compile error. @Repeatable requires a container annotation whose value() element is an array of the repeatable annotation.

NORMAL ~/memra/learn/java-from-zero/meta-annotations utf-8 LF