Annotations
An annotation is metadata you attach to code — a class, method, field, or parameter — using @Name syntax. Crucially, an annotation by itself doesn't change what your program does; it doesn't contain executable logic. What it does is provide information about your code to the compiler, to development tools, or to other code that inspects it at runtime (typically via reflection).
Common built-in annotations
Annotation | Purpose |
|---|---|
| Tells the compiler this method is meant to override a superclass method — if it doesn't actually match a superclass signature, compilation fails instead of silently creating a new method. |
| Marks a method, class, or field as discouraged for new use; the compiler emits a warning wherever it is referenced. |
| Tells the compiler to suppress specific warning categories (e.g. |
| Documents that an interface is intended to have exactly one abstract method (so it can be used as a lambda target) — the compiler enforces that constraint if you accidentally add a second abstract method. |
Built-in annotations in practice
public class Animal {
public String makeSound() {
return "...";
}
@Deprecated
public String oldMakeSound() {
return makeSound();
}
}
public class Dog extends Animal {
@Override
public String makeSound() { // compiler checks this really overrides Animal.makeSound
return "Woof!";
}
}
@FunctionalInterface
interface Greeter {
String greet(String name); // exactly one abstract method
}Writing a custom annotation
You can define your own annotations with the @interface keyword. Two meta-annotations control how a custom annotation behaves: @Target restricts what kinds of declarations it can be placed on (methods, fields, types, and so on), and @Retention controls how long the annotation information is kept — discarded after compilation, kept in the compiled .class file, or kept available at runtime so reflection can read it.
A simple custom annotation
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) // keep it available for reflection at runtime
@Target(ElementType.METHOD) // only methods can be annotated with this
public @interface Test {
}
public class Calculator {
@Test
public void additionWorks() {
// a testing framework could scan for @Test methods and run them
}
}Annotations attach metadata to code without changing its runtime behavior on their own.
@Override,@Deprecated,@SuppressWarnings, and@FunctionalInterfaceare common built-in annotations checked by the compiler.Custom annotations use
@interface;@Retentioncontrols how long they persist,@Targetrestricts where they can be used.Frameworks like Spring and JUnit combine custom annotations with reflection to power dependency injection and test discovery.