Java Annotations β @Override, @Deprecated and Custom Annotations
An annotation is a typed label you attach to code (classes, methods, fields, parameters, even types) β metadata the compiler, a framework or a build tool can read. Java has a handful of built-in annotations; frameworks like Spring, Hibernate and JUnit are built on custom ones.
Built-in annotations
| Annotation | Purpose |
|---|---|
@Override | Marks a method as overriding a supertype method. Catches typos at compile time. |
@Deprecated | Marks code that shouldn't be used anymore. @Deprecated(since, forRemoval) since Java 9. |
@SuppressWarnings | Silences specific compiler warnings β "unchecked", "rawtypes", "deprecation". |
@FunctionalInterface | Marks an interface as having exactly one abstract method (for lambdas). |
@SafeVarargs | Promises that a varargs method doesn't abuse its generic array. |
Examples
public class Car extends Vehicle {
@Override // compiler will error if signature is wrong
public String describe() { return "a car"; }
}
@Deprecated(since = "2.0", forRemoval = true)
public void oldMethod() { ... }
@SuppressWarnings("unchecked")
List<String> xs = (List<String>) raw;
@FunctionalInterface
interface Transformer<T, R> {
R apply(T input); // exactly one abstract method
}
Custom annotations
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME) // available at runtime via reflection
@Target(ElementType.METHOD) // can only annotate methods
public @interface Audited {
String action() default "";
String[] roles() default {};
}
// Usage:
@Audited(action = "delete", roles = {"admin"})
public void deleteUser(long id) { ... }
The meta-annotations
| Meta-annotation | What it controls |
|---|---|
@Retention | SOURCE (compiler only), CLASS (bytecode), RUNTIME (reflectable) |
@Target | Where the annotation can appear: TYPE, METHOD, FIELD, PARAMETER, TYPE_USE, β¦ |
@Inherited | Subclasses inherit the annotation |
@Documented | Included in Javadoc |
@Repeatable | Can be applied multiple times (Java 8+) |
Reading annotations at runtime
for (Method m : MyClass.class.getDeclaredMethods()) {
Audited a = m.getAnnotation(Audited.class);
if (a != null) {
System.out.println(m.getName() + " = " + a.action());
}
}
Where annotations rule
- Spring:
@Component,@Autowired,@RestController,@RequestMapping,@Transactional - JPA / Hibernate:
@Entity,@Id,@Column,@ManyToOne - JUnit:
@Test,@BeforeEach,@ParameterizedTest - Jackson:
@JsonProperty,@JsonIgnore - Lombok:
@Data,@Getter,@Setter,@Builder
All sub-topics
@Override@Deprecated@SuppressWarnings@FunctionalInterface- Writing custom annotations
- Meta-annotations (
@Retention,@Target)
Common mistakes
- Forgetting
@Retention(RUNTIME)β reflection won't see the annotation at runtime. - Not using
@Overrideβ a typo silently creates a new method. Always annotate. - Annotation bloat β a class drowning in annotations usually hides business logic in framework magic.
Try it & related tools
The JSON to POJO tool generates classes annotated for Jackson or Lombok. Run reflection code in the Java Online Compiler.