Annotations: Metadata on Your Code
Introduction
Annotations attach metadata to classes, methods, fields, and parameters. Tools (compiler, IDE, frameworks) read them for validation, documentation, or runtime behavior. You already used @Override in Inheritance; this chapter surveys built-in annotations, simple custom ones, and @FunctionalInterface before Functional Programming.
Prerequisites
What Is an Annotation
Syntax: @AnnotationName or @AnnotationName(value)
@Override
public String toString() {
return "Demo";
}Annotations do not change logic by themselves unless a processor or framework acts on them.
1) Built-in Annotations
| Annotation | Target (typical) | Purpose |
|---|---|---|
@Override | method | compiler checks override |
@Deprecated | class, method, field | marks obsolete API |
@SuppressWarnings | various | silence compiler warnings (use sparingly) |
@FunctionalInterface | interface | one abstract method contract |
@SafeVarargs | method/constructor | varargs generics warning |
@Override
@Override
public boolean equals(Object obj) {
// ...
}If parent signature changes, compiler error instead of silent bug.
@Deprecated
@Deprecated
public void oldApi() { }
// preferred replacement documented in Javadoc@SuppressWarnings
@SuppressWarnings("unchecked")
List raw = new ArrayList();Avoid blanket suppression—fix root cause when possible.
@FunctionalInterface
@FunctionalInterface
public interface Operation {
int apply(int a, int b);
}Compiler errors if a second abstract method appears.
2) Where Annotations Apply
Element types (meta-annotations on custom annotations):
TYPE— class, interface, enumMETHOD,FIELD,PARAMETER,CONSTRUCTORLOCAL_VARIABLE, etc.
3) Simple Custom Annotation
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Timed {
}public class Service {
@Timed
public void runTask() {
System.out.println("Running...");
}
}Retention policies:
SOURCE— discarded by compiler (e.g.@Override)CLASS— in bytecode, not runtime reflection by defaultRUNTIME— visible via reflection (frameworks)
Reading annotations at runtime uses reflection—advanced; frameworks like Spring/JUnit do this for you.
4) Annotation Parameters
public @interface Author {
String name();
String date();
}
@Author(name = "Team", date = "2026-05-17")
public class DocSample { }Default values possible in annotation declaration.
5) Link to Functional Programming
@FunctionalInterface documents Lambda targets:
@FunctionalInterface
interface Printer {
void print(String msg);
}
Printer p = msg -> System.out.println(msg);Common Beginner Mistakes
Missing @Override When Overriding
Risk of accidental overload instead of override.
Custom Annotation Without Retention
Reflection at runtime needs RUNTIME.
Overusing @SuppressWarnings
Hides real problems—narrow scope and document why.
Mini Practice
Create @Tag(String value) on methods; print tags in a demo runner via reflection (optional stretch) or just practice syntax.
What’s Next
FAQ
Do annotations slow programs?
Negligible. Runtime frameworks scan once at startup for many apps.
Are annotations only for frameworks?
No. They help documentation, static analysis, and team conventions too.
Difference between annotation and comment?
Comments are ignored by compiler. Annotations are structured metadata processors can read.
What reads @Test in JUnit?
JUnit runtime scans classes and runs annotated methods—example of framework processing.
Can I create annotations without reflection?
Yes—for SOURCE/CLASS retention used by compile-time tools only.