While Java's built-in annotations like @Override are extremely useful, Java also allows you to design your own custom annotations. When combined with reflection, custom annotations enable you to create highly flexible code layouts, frameworks, and dynamic behaviors.
In this guide, we will walk through declaring a custom annotation and reading its metadata values at runtime using Java reflection.
Imagine you run a factory and want to tag packages. Instead of standard tags, you create a custom sticker:
- The Stamp (
@interface): You design a stamp labeled "Priority Level". You can write any integer priority number on it. - Applying the Stamp (
@MyAnnotation(value = 10)): You stick the tag onto a specific shipping box. - Reading the Stamp (Reflection): The shipping coordinator scans the box, reads the priority level number, and processes the package accordingly.
1. Declaring the Custom Annotation
To define a custom annotation in Java, you use the @interface keyword. You also need to define its retention policy and target using meta-annotations:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) // Available to JVM at runtime
@Target(ElementType.METHOD) // Can only be placed on methods
@interface MyAnnotation {
int value(); // Attribute of the annotation
}
@Retention(RetentionPolicy.RUNTIME): Crucial step. If omitted, the annotation will be discarded by the compiler and won't be readable at runtime.@Target(ElementType.METHOD): Limits application to methods only (attempts to place it on class variables or classes will fail to compile).
2. Applying the Annotation
Once declared, applying the custom annotation is identical to using built-in annotations. You pass any required parameters inside parentheses:
class Hello {
@MyAnnotation(value = 10)
public void sayHello() {
System.out.println("hello annotation");
}
}
3. Accessing the Value at Runtime (Reflection)
To read the value from the annotation, we inspect the class methods using Java Reflection:
import java.lang.reflect.Method;
public class CustomAnnotation {
public static void main(String args[]) throws Exception {
Hello h = new Hello();
// Retrieve the method metadata object
Method m = h.getClass().getMethod("sayHello");
// Inspect the method for our custom annotation
MyAnnotation manno = m.getAnnotation(MyAnnotation.class);
// Print the extracted value
System.out.println("value is: " + manno.value()); // Prints 10
}
}
Conclusion
Custom annotations allow you to attach rich configuration directly to class structures. In professional development, frameworks like Spring and Hibernate use custom annotations to automate database mappings, inject dependencies, and control transaction cycles.