Java Tutorial

Operators

Flow Control

String

Number and Date

Built-in Classes

Array

Class and Object

Inheritance and Polymorphism

Exception Handling

Collections, Generics and Enumerations

Reflection

Input/Output Stream

Annotation

Java Custom Annotation

Annotations are a powerful feature in Java that provide metadata about your code. They can be used for various purposes, such as code generation, validation, or even runtime processing. In this tutorial, we'll cover how to create and use custom annotations in Java.

  • Creating a custom annotation

To create a custom annotation, use the @interface keyword instead of the class keyword. By convention, annotation names start with an uppercase letter (PascalCase). Annotations can have elements, which are similar to methods but without a body.

Example:

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CustomAnnotation {
    String value() default "Default value";
    int intValue() default 0;
}

In the example above, we created a custom annotation CustomAnnotation with two elements: value and intValue. We also used the built-in @Retention and @Target annotations to define the annotation's behavior:

  • @Retention: Specifies how long the annotation should be retained. In this case, we used RetentionPolicy.RUNTIME, which means the annotation will be available at runtime.
  • @Target: Specifies where the annotation can be used. In this case, we used ElementType.METHOD, which means the annotation can be applied to methods.
  • Using a custom annotation

To use a custom annotation, simply add it before the element it should annotate. In this case, we'll annotate methods.

Example:

public class Main {
    @CustomAnnotation(value = "Hello, World!", intValue = 42)
    public static void myMethod1() {
        System.out.println("Method 1");
    }

    @CustomAnnotation
    public static void myMethod2() {
        System.out.println("Method 2");
    }

    public static void main(String[] args) {
        myMethod1();
        myMethod2();
    }
}

In the example above, we used the CustomAnnotation annotation on two methods: myMethod1() and myMethod2(). For myMethod1(), we provided custom values for both elements, while for myMethod2(), we used the default values.

  • Accessing annotation values at runtime

To access the values of a custom annotation at runtime, use the Java Reflection API.

Example:

import java.lang.reflect.Method;

public class Main {
    @CustomAnnotation(value = "Hello, World!", intValue = 42)
    public static void myMethod1() {
        System.out.println("Method 1");
    }

    @CustomAnnotation
    public static void myMethod2() {
        System.out.println("Method 2");
    }

    public static void main(String[] args) {
        myMethod1();
        myMethod2();

        Class<?> clazz = Main.class;
        Method[] methods = clazz.getDeclaredMethods();

        for (Method method : methods) {
            if (method.isAnnotationPresent(CustomAnnotation.class)) {
                CustomAnnotation annotation = method.getAnnotation(CustomAnnotation.class);
                System.out.println("Method: " + method.getName());
                System.out.println("Value: " + annotation.value());
                System.out.println("Int value: " + annotation.intValue());
                System.out.println();
            }
        }
    }
}

In the example above, we used the Java Reflection API to access the CustomAnnotation values for each method in the Main class. The output will show the method names and the values of the value and intValue elements.

  1. Creating custom annotations in Java example

    Custom annotations are user-defined metadata that can be applied to Java code elements. Here's an example:

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    // Custom annotation definition
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyCustomAnnotation {
        String value() default "Default Value";
    }
    
  2. Annotation processors in Java for custom annotations

    Annotation processors allow you to process custom annotations at compile-time. You need to implement the AbstractProcessor class.

    import javax.annotation.processing.AbstractProcessor;
    import javax.annotation.processing.Processor;
    import javax.annotation.processing.RoundEnvironment;
    import javax.annotation.processing.SupportedAnnotationTypes;
    import javax.lang.model.element.Element;
    import javax.lang.model.element.TypeElement;
    import java.util.Set;
    
    @SupportedAnnotationTypes("MyCustomAnnotation")
    public class MyAnnotationProcessor extends AbstractProcessor implements Processor {
        @Override
        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
            // Process custom annotations here
            return true;
        }
    }
    
  3. Retrieving and using custom annotations in Java

    You can use reflection to retrieve and use custom annotations at runtime. Here's an example:

    import java.lang.reflect.Method;
    
    public class MyClass {
        @MyCustomAnnotation("Custom Value")
        public void myMethod() {
            // Retrieve and use custom annotation
            Method method = MyClass.class.getMethod("myMethod");
            MyCustomAnnotation customAnnotation = method.getAnnotation(MyCustomAnnotation.class);
            String value = customAnnotation.value();
            System.out.println("Annotation Value: " + value);
        }
    }
    
  4. Meta-annotations in Java custom annotations

    Meta-annotations are annotations applied to other annotations. Example:

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    // Meta-annotation
    @Target(ElementType.ANNOTATION_TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyMetaAnnotation {
        // Meta-annotation properties
    }
    
    // Custom annotation with meta-annotation
    @MyMetaAnnotation
    public @interface MyCustomAnnotation {
        // Custom annotation properties
    }
    
  5. Annotations in Java reflection API

    The Java reflection API allows you to inspect and manipulate class metadata at runtime. Example:

    import java.lang.reflect.Method;
    
    public class ReflectionExample {
        public static void main(String[] args) {
            // Using reflection to get annotations
            Method[] methods = MyClass.class.getDeclaredMethods();
            for (Method method : methods) {
                if (method.isAnnotationPresent(MyCustomAnnotation.class)) {
                    MyCustomAnnotation annotation = method.getAnnotation(MyCustomAnnotation.class);
                    String value = annotation.value();
                    System.out.println("Annotation Value: " + value);
                }
            }
        }
    }
    
  6. Inheritance and custom annotations in Java

    Custom annotations can be inherited by subclasses if they are annotated with @Inherited. Example:

    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    
    @Inherited
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyInheritedAnnotation {
        String value() default "Default Value";
    }
    
  7. Processing custom annotations at compile-time in Java

    To process custom annotations at compile-time, you can use annotation processors. Example:

    import javax.annotation.processing.*;
    import javax.lang.model.SourceVersion;
    import javax.lang.model.element.Element;
    import javax.lang.model.element.TypeElement;
    import java.util.Set;
    
    @SupportedAnnotationTypes("MyCustomAnnotation")
    @SupportedSourceVersion(SourceVersion.RELEASE_8)
    public class MyAnnotationProcessor extends AbstractProcessor {
        @Override
        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
            for (Element element : roundEnv.getElementsAnnotatedWith(MyCustomAnnotation.class)) {
                // Process elements with custom annotation
            }
            return true;
        }
    }