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
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.
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.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.
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.
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"; }
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; } }
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); } }
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 }
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); } } } }
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"; }
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; } }