• Home
  • LLMs
  • Docker
  • Kubernetes
  • Java
  • All
  • About
Java | Annotations
  1. Annotations
  2. @Target Annotation
  3. @Retention Annotation
  4. Create Your Own Annotation
  5. Read an Annotation via Reflection

  1. Annotations
    Annotations are a kind of metadata that can be associated with classes, interfaces, methods, fields, parameters, and other program elements.
    Annotations do not affect the runtime behavior of the code directly but can be used for various purposes: compile-time checking, code generation, runtime processing, and documentation.

    Example:
    public class AnnotationTest1 {
        @SuppressWarnings("unused")
        private void doSomething() {
        }
    }
    In the above example, without the @SuppressWarnings annotation, the compiler would display the following warning message: "The method doSomething() from the type AnnotationTest1 is never used locally".
  2. @Target Annotation
    This annotation (also called a meta-annotation since it applies to other annotations) is used to specify which program elements an annotation can be applied to.

    This annotation can be applied to the following elements:
    • ElementType.TYPE: class, interface, enum, and annotation declarations.
    • ElementType.FIELD: field declarations (including enum constants).
    • ElementType.METHOD: method declarations.
    • ElementType.PARAMETER: formal parameter declarations.
    • ElementType.CONSTRUCTOR: constructor declarations.
    • ElementType.LOCAL_VARIABLE: local variable declarations.
    • ElementType.ANNOTATION_TYPE: annotation type declarations.
    • ElementType.PACKAGE: package declarations.
    • ElementType.TYPE_PARAMETER: type parameter declarations.
    • ElementType.TYPE_USE: use of types.
    • ElementType.MODULE: module declarations.
    • ElementType.RECORD_COMPONENT: record component declarations.

    Example:
    package java.lang;
    
    import java.lang.annotation.*;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Override {
    }
    In the example above, the @Target annotation specifies that the @Override annotation can only be applied to method declarations.
  3. @Retention Annotation
    This annotation specifies how long an annotation should be retained:
    • RetentionPolicy.SOURCE: Annotations are discarded by the compiler and are not included in the class bytecode. Used primarily for compile-time processing and IDE support.
    • RetentionPolicy.CLASS: Annotations are recorded in the class bytecode but are not available at runtime via reflection. This is the default retention policy.
    • RetentionPolicy.RUNTIME: Annotations are recorded in the class bytecode and are available at runtime via reflection, allowing for runtime processing.

    Example:
    package java.lang;
    
    import java.lang.annotation.*;
    import static java.lang.annotation.ElementType.*;
    
    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SuppressWarnings {
        String[] value();
    }
    In the above example, the @Retention annotation specifies that the @SuppressWarnings annotation is only relevant during compilation and should not be retained in the class bytecode.
  4. Create Your Own Annotation
    The syntax for creating an annotation is similar to an interface declaration, using the @interface keyword.

    Inside the annotation body, you define methods (called elements or attributes) according to the following rules:
    • Method declarations must not have parameters or throw clauses.
    • Method return types are restricted to: primitives, String, Class, enum types, annotation types, and arrays of these types.
    • Methods can have default values using the default keyword.
    • If an annotation has only one element, it should be named value for convenience.

    Example:
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Annotation1 {
        double value() default 10.0;
    }
    When an annotation has a single element named value, the element name can be omitted when using the annotation. If a default value is provided and you want to use it, parentheses can be omitted entirely.

    Example:
    public class Test1Annotation1 {
        @Annotation1 // Uses default value (10.0)
        public Double myVar1;
    
        @Annotation1(1.2) // Shorthand for value = 1.2
        public Double myVar2;
    
        @Annotation1(value = 1.3) // Explicit element name
        public Double myVar3;
    }
    Annotations with no elements are called marker annotations and can be used without parentheses.
  5. Read an Annotation via Reflection
    Annotations with RetentionPolicy.RUNTIME can be accessed at runtime using Java's reflection API.

    Example:
    import java.lang.reflect.Field;
    
    public class Test2Annotation1 {
        @Annotation1
        public Double myVar1;
    
        @Annotation1(1.2)
        public Double myVar2;
    
        @Annotation1(value = 1.3)
        public Double myVar3;
    
        public static void main(String[] args) {
            Field[] fields = Test2Annotation1.class.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(Annotation1.class)) {
                    Annotation1 annotation = field.getAnnotation(Annotation1.class);
                    System.out.println("Field: " + field.getName() + ", Value: " + annotation.value());
                }
            }
        }
    }
    Output:
    Field: myVar1, Value: 10.0
    Field: myVar2, Value: 1.2
    Field: myVar3, Value: 1.3
© 2025  mtitek