In Advanced Java, combining annotations with reflection allows developers to create powerful, flexible, and dynamic systems. This capability is widely used in frameworks like Spring and Hibernate for dependency injection, ORM mapping, and more. This article explains step-by-step how to use annotations with reflection in Java.
Create a custom annotation with specific metadata using @Retention and @Target.
Example:
import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) // Annotation available at runtime @Target(ElementType.METHOD) // Annotation applicable to methods public @interface Info { String author(); String version(); }
Use the custom annotation on a method and provide values for its elements.
Example:
public class MyClass { @Info(author = "John Doe", version = "1.0") public void display() { System.out.println("This is a method with @Info annotation."); } }
Use reflection to inspect methods and retrieve annotation data at runtime.
Example:
import java.lang.reflect.Method; public class AnnotationProcessor { public static void main(String[] args) { try { // Get the Class object Class> clazz = MyClass.class; // Loop through all methods for (Method method : clazz.getDeclaredMethods()) { // Check if the method has @Info annotation if (method.isAnnotationPresent(Info.class)) { // Get the annotation Info info = method.getAnnotation(Info.class); // Print annotation details System.out.println("Method: " + method.getName()); System.out.println("Author: " + info.author()); System.out.println("Version: " + info.version()); } } } catch (Exception e) { e.printStackTrace(); } } }
Use the annotation metadata to implement specific behaviors dynamically. For instance, a method annotated with @Info could trigger logging or auditing functionality.
Example:
public class BehaviorExample { @Info(author = "Alice", version = "2.0") public void process() { System.out.println("Processing data..."); } public static void main(String[] args) { try { Class> clazz = BehaviorExample.class; Object instance = clazz.getConstructor().newInstance(); for (Method method : clazz.getDeclaredMethods()) { if (method.isAnnotationPresent(Info.class)) { Info info = method.getAnnotation(Info.class); System.out.println("Executing method: " + method.getName()); System.out.println("Author: " + info.author()); System.out.println("Version: " + info.version()); method.invoke(instance); // Dynamically invoke the method } } } catch (Exception e) { e.printStackTrace(); } } }
A real-world example is using annotations to validate fields in a class. Define a custom annotation for validation and use reflection to enforce the rules.
Example:
import java.lang.annotation.*; import java.lang.reflect.Field; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface NotNull { } class User { @NotNull private String username; public User(String username) { this.username = username; } } public class ValidationProcessor { public static void main(String[] args) { User user = new User(null); // Invalid user try { Class> clazz = user.getClass(); for (Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(NotNull.class)) { field.setAccessible(true); Object value = field.get(user); if (value == null) { System.out.println("Validation failed: " + field.getName() + " cannot be null."); } else { System.out.println("Validation passed for field: " + field.getName()); } } } } catch (Exception e) { e.printStackTrace(); } } }
Built-in annotations like @Override, @Deprecated, and @SuppressWarnings can also be processed using reflection.
Example:
public class BuiltInAnnotationProcessor { public static void main(String[] args) { Class> clazz = MyClass.class; for (Method method : clazz.getDeclaredMethods()) { if (method.isAnnotationPresent(Deprecated.class)) { System.out.println("Method " + method.getName() + " is deprecated."); } } } }
By combining annotations with reflection, developers can create flexible and dynamic systems in Advanced Java. This approach is a core technique in modern frameworks, enabling features like dependency injection, validation, and runtime processing of metadata.