Custom Annotations
TL;DR
- Custom Annotations allow you to define your own metadata tags using the
@interfacekeyword. - By themselves, they do absolutely nothing. They are just passive markers.
- They require a processor (usually written using Reflection) to scan for the annotation at runtime and execute corresponding logic.
Concept
To define an annotation, you must provide two essential Meta-Annotations:
@Retention: Specifies how long the annotation is kept.SOURCE: Thrown away by the compiler (e.g.,@Override).CLASS: Written to the.classfile but ignored at runtime (Default).RUNTIME: Loaded into JVM memory. Required if you want to read it via Reflection.
@Target: Specifies where the annotation can be applied (e.g.,METHOD,FIELD,TYPEfor classes).
You can also define elements (properties) inside the annotation. They look like interface methods but act like configuration fields.
Examples
import java.lang.annotation.*;
import java.lang.reflect.Method;
// 1. DEFINE THE ANNOTATION
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExecuteTimes {
int value() default 1; // 'value' is a special name. It allows @ExecuteTimes(5)
}
// 2. USE THE ANNOTATION
class TaskRunner {
@ExecuteTimes(3)
public void doWork() {
System.out.println("Working...");
}
}
// 3. PROCESS THE ANNOTATION VIA REFLECTION
public class AnnotationDemo {
public static void main(String[] args) throws Exception {
TaskRunner runner = new TaskRunner();
Method method = TaskRunner.class.getMethod("doWork");
// Check if the annotation is present
if (method.isAnnotationPresent(ExecuteTimes.class)) {
// Retrieve the annotation instance
ExecuteTimes annotation = method.getAnnotation(ExecuteTimes.class);
// Read the property and execute the logic
int times = annotation.value();
for (int i = 0; i < times; i++) {
method.invoke(runner);
}
}
}
}
Interview Questions
Q: What types can you use for an Annotation element?
A: Annotation elements are strictly limited. They can only return:
- Primitives (
int,boolean,double, etc.) StringClass- An Enum
- Another Annotation
- A 1-dimensional array of any of the above.
You cannot return aList<String>or an instance of a normal custom object (likeUser).
Q: What does the @Inherited meta-annotation do?
A: By default, if you put a custom annotation on a parent class, a child class extending it does not inherit that annotation. If you apply the @Inherited meta-annotation to your custom annotation definition, it tells the JVM that any class inheriting from the annotated class should also be considered to have the annotation. (Note: This only applies to class-level annotations, not methods or fields).