Retention и Target

Базовый Java
≈ 2 мин чтения

Retention: как долго живёт аннотация

Не каждой аннотации нужно попадать в работающую программу. Мета-аннотация @Retention задаёт момент, до которого информация об использовании аннотации должна сохраняться.

  • RetentionPolicy.SOURCE — аннотация нужна только в исходном коде и отбрасывается компилятором.
  • RetentionPolicy.CLASS — сохраняется в class-файле, но не обязана быть доступна через Reflection во время выполнения. Это политика по умолчанию.
  • RetentionPolicy.RUNTIME — сохраняется до времени выполнения и может быть прочитана через Reflection.
@Retention(RetentionPolicy.RUNTIME)
public @interface Audit {
    String action();
}

Если приложение должно обнаруживать @Audit во время выполнения, для неё нужна именно политика RUNTIME.

Target: где разрешена аннотация

Мета-аннотация @Target ограничивает места, где разрешено использовать пользовательскую аннотацию. Это помогает сделать её назначение явным и позволяет компилятору ловить неправильное применение.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Audit {
    String action();
}

Теперь @Audit можно поставить на метод, но нельзя случайно повесить на поле или класс. Если допустимо несколько мест, в @Target передаётся массив значений.

@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Marker {
}

Среди значений ElementType есть цели для типов, полей, методов, параметров, конструкторов, локальных переменных, модулей, компонентов record, параметров типов и использования типов. Выбирать стоит только те цели, которые действительно имеют смысл для конкретной метаинформации.

RUNTIME не означает «выполни аннотацию». Эта политика лишь делает метаданные доступными во время выполнения. Чтобы они повлияли на поведение программы, кто-то должен прочитать и обработать их.