When working with Java reflection to inspect annotations, a common issue arises where isAnnotationPresent() returns false, or getAnnotation() returns null, despite the annotation being clearly present in the source code. This behavior is frequently caused by an incorrect retention policy definitino.
To retrieve annotation data at runtime, the annotation must be defined with a runtime retention policy.
First, define the custom annotation. It is crucial to annotate the interface with @Retention(RetentionPolicy.RUNTIME). Without this, the compiler will discard the annotation information during the compilation process, making it unavailable too the JVM during execution.
package com.example.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EntityDescriptor {
String description();
}
Next, apply this annotation to a class. Here, the EntityDescriptor is attached to the Employee class.
package com.example.model;
import com.example.annotation.EntityDescriptor;
@EntityDescriptor(description = "Employee Data Object")
public class Employee {
private String id;
private String name;
public Employee(String id, String name) {
this.id = id;
this.name = name;
}
// Getters and setters
}
Finally, use reflection to access the annotation. The following code snippet loads the class and checks for the presence of the annotation.
package com.example;
import com.example.annotation.EntityDescriptor;
import com.example.model.Employee;
public class AnnotationScanner {
public static void main(String[] args) {
try {
// Load the target class
Class<?> clazz = Class.forName("com.example.model.Employee");
// Check if the annotation is present
if (clazz.isAnnotationPresent(EntityDescriptor.class)) {
EntityDescriptor descriptor = clazz.getAnnotation(EntityDescriptor.class);
System.out.println("Annotation Found: " + descriptor.description());
} else {
System.out.println("Annotation is not visible at runtime.");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
If the retention policy was mistakenly set to RetentionPolicy.SOURCE, the output would indicate that the annotation is not visible. RetentionPolicy.SOURCE instructs the compiler to record the annotation in the source code but discard it in the generated class file. Consequently, the reflection API cannot locate it at runtime. Always ensure RetentionPolicy.RUNTIME is specified when annotation data needs to be accessed dynamically via reflection.