Удобно рассмотреть случаи применения
аннотаций с точки зрения возможных значений их свойства
RetentionPolicy:
SOURCE – аннотация присутствует только в исходном коде, но не вовлечена в компиляцию. Можно разделить их на две категории:
Первая – аннотации для программиста, а не для программы. Это всевозможные
маркеры. Они добавляют аннотируемым элементам некоторую специальную семантику. Более формализованный вариант документации. Примеры –
@Immutable и
@ThreadSafe из Hibernate.
Вторая категория –
инструкции для инструментов разработки. Примеры этой категории,
@SuppressWarnings и
@Override могут влиять на предупреждения и ошибки компиляции. IntelliJ IDEA умеет понимать
@Nullable и
@NonNull из Spring Framework, и предупреждать о возможных
NullPointerException.
CLASS – самое экзотическое, но при том стандартное значение. Аннотация попадает в байткод
.class-файла, но игнорируется
загрузчиком классов. В результате такая аннотация недоступна для рефлекшна. Используется
для сторонних инструментов, обрабатывающих байткод,
например для обфускаторов.
RUNTIME – самое ходовое значение. Цель
снабжается метаинформацией, доступной во время выполнения программы. Сама по себе аннотация всё так же не добавляет нового поведения. Для практической пользы runtime-аннотации в программе должен быть исполнен некоторый код процессинга, который
прочитает метаинформацию инструментами Reflection API. Такой механизм широко используется во множестве популярных фреймворков: Spring, Hibernate, Jackson.