Annotations

Core Java · lesson 34 of 42 · 3 min read

Use the built-in annotations, declare your own, and see which ones reach the runtime.

Open this lesson in the learning hub

Key points

  • An annotation is metadata attached to code. On its own it does nothing — something has to read it.
  • @Override makes the compiler prove the method really overrides one, so a typo fails the build.
  • @Deprecated, @SuppressWarnings and @FunctionalInterface are the three others you meet daily.
  • Declare one with @interface. Its members look like methods and may carry a default.
  • @Retention decides who sees it: SOURCE stops at javac, only RUNTIME reaches reflection.
  • @Target limits where it may be written. A framework is mostly RUNTIME annotations plus a scanner.

Example

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Comparator;

public class Main {

    @Retention(RetentionPolicy.RUNTIME)      // survives into the running JVM
    @Target(ElementType.METHOD)              // may only be written on a method
    @interface Job {
        String name();
        int everyMinutes() default 60;
    }

    static class Tasks {
        @Job(name = "nightly-report")
        void report() {}

        @Job(name = "cache-sweep", everyMinutes = 5)
        void sweep() {}

        void plainMethod() {}
    }

    static class Base {
        @Override public String toString() { return "Base"; }
    }

    static class Child extends Base {
        @Override public String toString() { return "Child, and @Override proved it overrides"; }
    }

    @Deprecated
    static String legacy() { return "still runs, just flagged"; }

    public static void main(String[] args) {
        System.out.println(new Child());
        System.out.println("@Deprecated: " + legacy());

        Method[] methods = Tasks.class.getDeclaredMethods();
        Arrays.sort(methods, Comparator.comparing(Method::getName));
        for (Method m : methods) {
            Job job = m.getAnnotation(Job.class);
            System.out.println(m.getName() + " -> "
                    + (job == null ? "no @Job" : job.name() + " every " + job.everyMinutes() + " min"));
        }

        System.out.println("@Override is SOURCE retention, so reflection can never see it");
        System.out.println("that scan above is exactly how a framework finds your beans");
    }
}

An annotation is a label; retention decides who is still around to read it.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Core Java course, and every lesson in it is listed on the Core Java contents page.