Introduced in Java 5, Annotations provide structured metadata about your code without affecting program semantics. Instead of fragile XML configuration files, modern Java uses annotations to configure web routes, test suites, database columns, and validation constraints.
| Annotation | Target | Purpose |
|---|---|---|
@Override | Method | Instructs compiler to verify that the method correctly overrides a superclass method. Prevents typo bugs. |
@Deprecated | Type / Method / Field | Warns developers that an element is obsolete and may be removed in future versions. |
@SuppressWarnings | Any | Suppresses specific compiler warnings (e.g., @SuppressWarnings("unchecked")). |
@FunctionalInterface | Interface | Enforces that an interface contains exactly one single abstract method (SAM) for lambdas. |
@SafeVarargs | Method / Constructor | Asserts that the method body does not perform unsafe operations on its varargs parameter. |
Meta-annotations in java.lang.annotation define how custom annotations behave:
| Meta-Annotation | Values | Explanation |
|---|---|---|
@Retention | RetentionPolicy.SOURCERetentionPolicy.CLASSRetentionPolicy.RUNTIME | Specifies how long the annotation is retained. RUNTIME is required to inspect via Reflection. |
@Target | ElementType.TYPEElementType.METHODElementType.FIELD | Specifies where the annotation may be placed (classes, methods, fields, etc.). |
@Documented | None | Includes annotation information in generated Javadoc documentation. |
@Inherited | None | Allows subclasses to automatically inherit the annotation from their parent class. |
Let's build a practical custom annotation: @JsonField to customize JSON property names and serialization behavior:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 1. Define meta-annotations
@Retention(RetentionPolicy.RUNTIME) // Must be readable at runtime
@Target(ElementType.FIELD) // Can only be placed on fields
public @interface JsonField {
String name() default ""; // Custom property name
boolean required() default true; // Validation constraint
}
import java.lang.reflect.Field;
// Target class using our custom annotation
class UserProfile {
@JsonField(name = "user_full_name", required = true)
private String fullName = "Aarav Sharma";
@JsonField(name = "user_email")
private String email = "aarav@veewom.com";
private String internalPassword = "Confidential_Hash"; // Not annotated
}
// Annotation Processor Engine
public class AnnotationParser {
public static void main(String[] args) throws Exception {
UserProfile profile = new UserProfile();
Class> clazz = profile.getClass();
System.out.println("Parsing JSON Mappings for: " + clazz.getSimpleName());
for (Field field : clazz.getDeclaredFields()) {
// Check if field is annotated with @JsonField
if (field.isAnnotationPresent(JsonField.class)) {
field.setAccessible(true);
JsonField annotation = field.getAnnotation(JsonField.class);
String jsonKey = annotation.name().isEmpty() ? field.getName() : annotation.name();
Object value = field.get(profile);
boolean isRequired = annotation.required();
System.out.printf("Field: '%s' -> JSON Key: '%s' | Value: '%s' | Required: %b%n",
field.getName(), jsonKey, value, isRequired);
}
}
}
}
Parsing JSON Mappings for: UserProfile Field: 'fullName' -> JSON Key: 'user_full_name' | Value: 'Aarav Sharma' | Required: true Field: 'email' -> JSON Key: 'user_email' | Value: 'aarav@veewom.com' | Required: true
@Retention(RetentionPolicy.RUNTIME) on a custom annotation?
RetentionPolicy.CLASS. While recorded in the compiled .class file, the JVM execution engine strips it out during class loading. Calling field.getAnnotation() at runtime will return null.@interface implicitly extends java.lang.annotation.Annotation, and annotation elements cannot declare parameters or throw exceptions.Accelerate your Java mastery by studying these tightly connected core tutorials:
Reading custom annotations at runtime.
Using @Override for compiler safety.
Interface foundations of @interface.
Framework patterns driven by annotations.