Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

Java annotations are a formalized metadata facility that provides data about a program but is not part of the program’s executable logic. Implemented as a specialized type of Java interface extending java.lang.annotation.Annotation, annotations have no direct effect on the operation of the code they decorate. Instead, they embed structural, lifecycle, or behavioral metadata into the abstract syntax tree (AST) or compiled bytecode, which is subsequently consumed by the compiler, build tools, or the Java Virtual Machine (JVM).

Syntax and Declaration

Annotations are declared using the @interface keyword. The attributes of an annotation are declared as method signatures without parameters or throws clauses. These are formally called elements.
public @interface ConfigurationMetadata {
    // Element with a defined type and no default value (mandatory)
    String author();

    // Element with a default value (optional)
    int revision() default 1;

    // Elements are restricted to primitives, String, Class, enums, 
    // other annotations, or 1-dimensional arrays of these types.
    String[] tags() default {};
}
When applying an annotation, elements are populated using key-value pairs. The key can be omitted during application if the element being assigned is named value and it is either the only element in the annotation, or all other elements in the annotation possess default values.
public @interface Priority {
    int value();
    String level() default "INFO";
}

// The key "value =" is omitted because 'level' has a default value
@Priority(5)
public class BackgroundTask {
    // Class implementation
}

Meta-Annotations

The behavior, scope, and lifecycle of a custom annotation are governed by meta-annotations—annotations that are applied to the declaration of other annotations.

@Retention

Specifies the lifecycle of the annotation using the java.lang.annotation.RetentionPolicy enum:
  • SOURCE: Retained only in the source code and discarded by the compiler.
  • CLASS: (Default) Compiled into the .class file and loaded by the JVM. It remains accessible to bytecode analysis tools and the JVM Tool Interface (JVM TI), but it is ignored by and inaccessible to the standard Java Reflection API at runtime.
  • RUNTIME: Compiled into the .class file and retained by the JVM at runtime, making it fully accessible via the Java Reflection API.

@Target

Restricts the syntactic contexts where the annotation can be applied, using the java.lang.annotation.ElementType enum. Common targets include:
  • TYPE: Classes, interfaces, or enums.
  • FIELD: Instance or static variables.
  • METHOD: Method declarations.
  • PARAMETER: Method parameters.
  • TYPE_USE: Any use of a type (introduced in Java 8 for stronger type checking).

@Inherited

Indicates that an annotation applied to a superclass is automatically inherited by its subclasses. This only applies to class-level annotations (ElementType.TYPE) and does not affect interfaces or implemented methods.

@Repeatable

Introduced in Java 8, this allows the same annotation to be applied multiple times to a single declaration. It requires a container annotation that holds an array of the repeatable annotation.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(Schedules.class)
public @interface Schedule {
    String dayOfMonth() default "first";
    String dayOfWeek() default "Mon";
}

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

Internal Mechanics

Under the hood, an annotation is not instantiated like a standard class. When a RUNTIME retained annotation is queried via the Reflection API (e.g., Class.getAnnotation(Class)), the JVM dynamically generates a proxy class (using java.lang.reflect.Proxy) that implements the annotation’s interface. The JVM maps the element values stored in the class file’s constant pool to the methods of this dynamic proxy. Invoking an element method on the retrieved annotation object routes through a JVM-specific internal InvocationHandler implementation, which returns the constant value bound to that element during compilation.
Master Java with Deep Grasping Methodology!Learn More