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

AnnotationPurpose
@OverrideMarks a method as overriding a supertype method. Catches typos at compile time.
@DeprecatedMarks code that shouldn't be used anymore. @Deprecated(since, forRemoval) since Java 9.
@SuppressWarningsSilences specific compiler warnings β€” "unchecked", "rawtypes", "deprecation".
@FunctionalInterfaceMarks an interface as having exactly one abstract method (for lambdas).
@SafeVarargsPromises 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-annotationWhat it controls
@RetentionSOURCE (compiler only), CLASS (bytecode), RUNTIME (reflectable)
@TargetWhere the annotation can appear: TYPE, METHOD, FIELD, PARAMETER, TYPE_USE, …
@InheritedSubclasses inherit the annotation
@DocumentedIncluded in Javadoc
@RepeatableCan 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

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.