Java Annotations
An annotation is a label that you attach to a class, method, or variable. The label starts with the @ sign. Annotations give extra information to the compiler and to tools. They do not change what your code does by themselves.
A Luggage Tag Example
Airlines attach tags to bags. A tag reads "Fragile" or "Heavy". The tag does not change the bag, yet the airport staff handle the bag in a different way. Annotations work as tags on code.
Diagram: Tags on Code
@Override <-- tag
void show() { } <-- code
@Deprecated <-- tag
void oldMethod() { } <-- code
Built-In Annotations
| Annotation | Purpose |
|---|---|
| @Override | Checks that a method replaces a parent method |
| @Deprecated | Warns that a feature is old |
| @SuppressWarnings | Hides chosen compiler warnings |
| @FunctionalInterface | Checks that an interface has one abstract method |
@Override in Action
class Animal {
void sound() { }
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Woof");
}
}
@Deprecated in Action
class Printer {
@Deprecated
void oldPrint() { }
void print() { }
}
Code that calls oldPrint shows a warning, so developers move to print.
@SuppressWarnings in Action
@SuppressWarnings("unchecked")
void legacyCode() {
java.util.List list = new java.util.ArrayList();
list.add("text");
}
@FunctionalInterface in Action
@FunctionalInterface
interface Greeter {
void greet(String name);
}
An extra abstract method in Greeter triggers a compile error.
Creating Your Own Annotation
Use the @interface keyword. Two helper annotations control the new annotation. @Target says where you can place it. @Retention says how long it lives.
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Task {
String owner();
int priority() default 1;
}
Retention Choices
| Policy | Lifetime |
|---|---|
| SOURCE | Only in source code, dropped by the compiler |
| CLASS | Stored in the class file, not visible at run time |
| RUNTIME | Visible while the program runs |
Using the Custom Annotation
class Work {
@Task(owner = "Asha", priority = 2)
void clean() { }
}
Reading an Annotation at Run Time
A program reads RUNTIME annotations through the reflection feature.
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception {
Method m = Work.class.getDeclaredMethod("clean");
Task t = m.getAnnotation(Task.class);
System.out.println(t.owner() + " " + t.priority()); // Asha 2
}
}
Diagram: Who Reads the Tag
@Override --> compiler checks it @Task --> your program reads it while running @Entity --> a framework reads it to build database tables
Where You See Annotations
- Testing tools mark test methods with annotations
- Web frameworks mark classes that handle web requests
- Database tools mark fields that map to table columns
Common Mistakes
- Forgetting RetentionPolicy.RUNTIME and reading null at run time
- Skipping @Override and missing spelling errors
- Leaving out a required annotation value
Real Example: Marking Slow Methods
A team wants to list every method that needs speed checks. Developers create a Slow annotation and tag each method. A small tool scans the class and prints the tagged names. The tags stay next to the code, so nobody maintains a separate list.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Slow { }
class Report {
@Slow
void buildYearlyReport() { }
void showTitle() { }
}
The scan tool checks each method with isAnnotationPresent and reports buildYearlyReport only.
Quick Summary
- Annotations are labels that start with @
- Built-in annotations help the compiler
- Custom annotations use @interface, @Target, and @Retention
