Java Annotations
A Java annotation is metadata attached to code. An annotation does not usually change the code by itself, but tools, compilers, frameworks, or reflection code can read it and act on it.
Annotations are common in Java libraries and frameworks. For example, they can mark overridden methods, describe tests, configure web routes, or tell a tool how to process a class.
Built-In Annotations
Java includes several annotations that you can use immediately. The most common ones are @Override, @Deprecated, and @SuppressWarnings.
| Annotation | Meaning |
|---|---|
@Override |
Tells the compiler that a method must override a method from a superclass or interface. |
@Deprecated |
Marks code that should no longer be used. |
@SuppressWarnings |
Asks the compiler to hide a specific warning in a limited place. |
class Parent {
void start() {
System.out.println("Parent start");
}
}
class Child extends Parent {
@Override
void start() {
System.out.println("Child start");
}
@Deprecated
void oldStart() {
System.out.println("Old start");
}
}
public class Main {
public static void main(String[] args) {
Child child = new Child();
child.start();
child.oldStart();
}
}
Output:
Child start
Old start
The @Override annotation helps catch mistakes. If you misspell start in Child, the compiler reports an error because the method no longer overrides anything. The @Deprecated annotation allows old code to keep compiling while warning programmers to choose a newer option.
Creating A Custom Annotation
You can create your own annotation with @interface. Annotation elements look like methods, but they define values that can be supplied when the annotation is used.
@interface CourseInfo {
String topic();
int level() default 1;
}
@CourseInfo(topic = "Annotations", level = 3)
class Lesson {
}
public class Main {
public static void main(String[] args) {
System.out.println("Lesson class created");
}
}
Output:
Lesson class created
The CourseInfo annotation has two elements: topic and level. The level element has a default value, so code can omit it when level 1 is correct.
Retention And Target
Two important meta-annotations control where an annotation can be used and how long it is kept.
@Targetlimits where the annotation is allowed, such as on a class, method, field, or parameter.@Retentioncontrols whether the annotation is kept only in source code, stored in the compiled class file, or available at runtime.
Use RetentionPolicy.RUNTIME when your program needs to read the annotation while it is running. Use ElementType.TYPE when the annotation should be placed on classes, interfaces, enums, records, or annotation types.
Reading Annotations With Reflection
Reflection lets a running Java program inspect classes and their annotations. This is how many frameworks discover configuration written with annotations.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Feature {
String name();
String owner() default "Team A";
}
@Feature(name = "Reports", owner = "Data Team")
class ReportService {
}
public class Main {
public static void main(String[] args) {
Class<ReportService> type = ReportService.class;
Feature feature = type.getAnnotation(Feature.class);
System.out.println(feature.name());
System.out.println(feature.owner());
}
}
Output:
Reports
Data Team
The annotation is available because it uses @Retention(RetentionPolicy.RUNTIME). Without runtime retention, getAnnotation would not return this metadata while the program is running.
Common Annotation Element Types
Annotation elements can use only certain types: primitives, String, Class, enum types, annotation types, and arrays of those types. They cannot use arbitrary objects such as ArrayList.
If an annotation has one element named value, Java lets you omit the element name when using it. For example, @SuppressWarnings("unchecked") is short for @SuppressWarnings(value = "unchecked").
When To Use Annotations
- Use annotations for metadata that belongs directly on a class, method, field, or parameter.
- Use built-in annotations such as
@Overridewhenever they help the compiler check your intent. - Create custom annotations when another tool, framework, or reflection code will read them.
- Do not use annotations as a replacement for normal program data that changes while the program runs.
Takeaway: annotations attach structured metadata to Java code, and runtime annotations can be inspected with reflection when a program or framework needs that information.
