Как работает аннотация, если она нужна только для компиляции, а не для runtime
Что проверяют
Знаете ли вы три значения RetentionPolicy и понимаете ли, кто на самом деле выполняет работу, если аннотация до рантайма не доживает. Следом обычно спрашивают, как устроены Lombok или MapStruct и почему своя аннотация не видна через рефлексию.
Как отвечать
Аннотация сама по себе ничего не делает, это метаданные. Срок их жизни задаёт @Retention:
SOURCE: компилятор отбрасывает аннотацию, в.classеё нет. Так объявлены@Override,@SuppressWarningsи аннотации Lombok;CLASS: значение по умолчанию, если@Retentionне указан. Аннотация записывается в байт-код, но через рефлексию в рантайме не видна. Её читают инструменты анализа байт-кода;RUNTIME: доступна черезgetAnnotation(), на ней держатся Spring, JPA, Jackson.
С SOURCE-аннотациями работают двое:
- сам
javac: для@Overrideпроверяет, что метод действительно переопределяет родительский, иначе ошибка компиляции; - процессоры аннотаций (JSR 269): класс наследует
AbstractProcessor, регистрируется вMETA-INF/services/javax.annotation.processing.Processorи вызывается компилятором раундами. ЧерезFilerон генерирует новые исходники, черезMessagerсообщает об ошибках. Так работают MapStruct, Dagger, AutoValue.
Менять существующие классы официальный API процессору не даёт. Lombok, который дописывает геттеры прямо в класс, для этого лезет во внутренний AST компилятора, поэтому временами ломается на новых версиях JDK.
Подключение в сборке: annotationProcessor в Gradle или annotationProcessorPaths в maven-compiler-plugin. В свежих JDK процессоры, лежащие просто на classpath, по умолчанию не запускаются, их указывают явно.
Где спотыкаются
Пишут свою аннотацию для аспекта или проверки в Spring и забывают @Retention(RUNTIME). По умолчанию будет CLASS, и isAnnotationPresent() вернёт false.
Приводят @Deprecated как пример аннотации только для компиляции. У неё RUNTIME, её видно через рефлексию.
Говорят, что такие аннотации нужны компилятору «для оптимизации». javac почти ничего не оптимизирует и на аннотации в этом смысле не смотрит, их задача это проверки и генерация кода.