Аннотации Java

Аннотация — структурированные метаданные, привязанные к элементу программы. Сама по себе она ничего не выполняет: смысл придаёт компилятор, annotation processor, фреймворк или код через reflection.

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Required {
    String message() default "value is required";
}
 
final class Command {
    @Required
    private String id;
}

Мета-аннотации

АннотацияНазначение
@Targetдопустимые места применения
@Retentionкак долго хранится: SOURCE, CLASS, RUNTIME
@Documentedвключать в Javadoc
@Inheritedнаследовать аннотацию класса подклассом
@Repeatableразрешить несколько экземпляров

@Inherited работает только при поиске аннотаций на классах: методы и интерфейсы через неё автоматически не наследуют метаданные.

Элемент аннотации может быть примитивом, String, Class, enum, другой аннотацией или массивом этих типов. Значение обязано быть compile-time допустимым; null использовать нельзя.

Два времени обработки

  • compile time: генерация кода, проверка соглашений, @Override;
  • runtime: контейнер читает RUNTIME-аннотации и строит поведение, например маршрутизацию или транзакционный proxy.
boolean required = Command.class
        .getDeclaredField("id")
        .isAnnotationPresent(Required.class);

Reflection на каждом запросе дорог и многословен, поэтому фреймворки обычно сканируют метаданные при старте и кэшируют результат.

Частые ошибки

  • ожидать runtime-доступ от RetentionPolicy.CLASS;
  • думать, что аннотация сама перехватит вызов метода;
  • забывать @Target и разрешать бессмысленное применение;
  • прятать важную бизнес-логику за множеством неочевидных аннотаций.

На собеседовании

Что делает аннотация после добавления в код? Ничего без потребителя её метаданных.

Какая retention нужна для reflection? RUNTIME.

Работает ли @Inherited для методов? Нет.

Чем annotation processor отличается от reflection? Первый работает во время компиляции, второй исследует загруженные типы во время выполнения.

Связано: Понятие рефлективность Java, Класс Class, Аннотация Cacheable.