Meta Annotation

Overview of meta-annotation in Java.

About

In Java, meta-annotations are annotations that apply to other annotations. They define how custom annotations behave and are an essential part of building a clean, consistent annotation-based system in any Java application or framework.

Just like classes can be described by annotations, annotations themselves can also be described—this is what meta-annotations are for.

Why Meta-Annotations?

When creating custom annotations, we often need to define:

  • Where it can be applied (e.g., on methods, classes, fields)

  • How long it should be retained (e.g., only in source code or also at runtime)

  • Whether it should be inherited

  • Whether it can be repeated

  • Whether it should appear in the generated Javadocs

These aspects are controlled using meta-annotations.

Available Meta-Annotations in Java

Java provides five core meta-annotations in the java.lang.annotation package

Meta-Annotation
Description

@Target

Specifies where the annotation can be applied.

@Retention

Defines how long the annotation is retained (source, class, or runtime).

@Inherited

Allows the annotation to be inherited by subclasses.

@Documented

Marks the annotation to be included in Javadocs.

@Repeatable

Allows an annotation to be applied multiple times to the same element.

@Target

Specifies the valid locations (or elements) where the annotation can be used, such as methods, fields, constructors, parameters, etc.

@Target(ElementType.METHOD)
public @interface MyAnnotation {}

Possible ElementType values

ElementType
Description

TYPE

Class, interface, or enum

FIELD

Fields (instance variables)

METHOD

Methods

PARAMETER

Method parameters

CONSTRUCTOR

Constructors

LOCAL_VARIABLE

Local variables inside methods

ANNOTATION_TYPE

Other annotations

PACKAGE

Java packages

TYPE_USE

Any use of a type (generics, casts, etc.)

MODULE

Java 9 modules

Example

@Target({ElementType.METHOD, ElementType.TYPE})
public @interface AuditLog {}

@Retention

Defines how long the annotation is retained in the program lifecycle.

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

Retention policies

Policy
Description

SOURCE

Available only in source code. Removed during compilation.

CLASS

Present in the .class file but not accessible at runtime via reflection.

RUNTIME

Present in the .class file and available via reflection at runtime.

Example

@Retention(RetentionPolicy.CLASS)
public @interface CompileOnly {}

@Inherited

Specifies that if a class is annotated, then its subclasses will automatically inherit the annotation.

Note: This only applies to class-level annotations, not methods or fields.

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

@Secured
public class BaseService {}

public class UserService extends BaseService {}

Here, UserService will be treated as if it has @Secured even though it is not explicitly annotated.

@Documented

Indicates that the annotation should be included in the generated Javadoc.

Without this, annotations are not visible in Javadoc output by default.

@Documented
@Target(ElementType.METHOD)
public @interface DeveloperNote {
    String value();
}

@Repeatable

Allows the same annotation to be used multiple times on the same element.

Prior to Java 8, an annotation could be applied only once on a target.

How it works ?

We must define a container annotation to hold the repeated annotations.

// Repeatable annotation
@Repeatable(Schedules.class)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Schedule {
    String day();
}

// Container annotation
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Schedules {
    Schedule[] value();
}

Usage

@Schedule(day = "Monday")
@Schedule(day = "Friday")
public void generateReport() {}

Last updated