@Retention аннотаций проверки типа Java

Аннотации типа Java 8 (JSR 308) позволяют контролерам типов выполнять статический анализ кода. Например, The Checker Framework может проверять возможную нулевость с помощью аннотаций @NonNull.

Различные проекты определяют свои собственные аннотации NonNull, например:

Для таких аннотаций я ожидал бы, что @interface имеет @Retention(RetentionPolicy.CLASS), потому что они обычно не требуется во время выполнения. Самое главное, что код не имеет зависимостей времени выполнения от соответствующей библиотеки.

В то время как org.eclipse.jdt.annotation.NonNull следует этому подходу, большинство других аннотаций NonNull, таких как javax.annotation.Nonnull (JSR 305) и org.checkerframework.checker.nullness.qual.NonNull, @Retention(RetentionPolicy.RUNTIME). Есть ли какая-то особая причина для RetentionPolicy.RUNTIME в этих аннотациях?


Уточнение: Checker Framework поддерживает аннотации комментариев для обратной совместимости. Однако использование тех, что в Java 8, чтобы избежать зависимостей во время выполнения, похоже на грязный взлом.

Ответ 1

Это хороший вопрос.

Для статической проверки во время компиляции сохранение CLASS было бы достаточно. Обратите внимание, что сохранение SOURCE не будет достаточным из-за отдельной компиляции: при проверке типов класса компилятору необходимо прочитать аннотации в библиотеках, которые он использует, а отдельно компилируемые библиотеки доступны компилятору только как файлы классов.

Дизайнеры аннотаций использовали RUNTIME сохранение, чтобы позволить инструментам выполнять операции во время выполнения. Это может включать проверку аннотаций (например, утверждение assert), проверку типов динамически загружаемого кода, проверку операций отбрасывания и instanceof, более точное отражение отражения и многое другое. Сегодня не так много таких инструментов, но дизайнеры аннотаций хотели разместить их в будущем.

Вы заметили, что при @Retention(RetentionPolicy.CLASS) "код не имеет зависимостей во время выполнения от соответствующей библиотеки". Это действительно верно и для @Retention(RetentionPolicy.RUNTIME)! См. Этот вопрос о переполнении стека: Почему отсутствующая аннотация не вызывает исключение ClassNotFoundException во время выполнения?.

Таким образом, использование CLASS удерживает затраты на незначительное количество пространства во время выполнения, позволяет использовать больше потенциальных возможностей в будущем и не вводит зависимость времени выполнения.

В случае Checker Framework он предлагает тесты времени выполнения, такие как isRegex(String). Если ваш код использует такие методы, ваш код будет зависеть от библиотеки времени выполнения Checker Framework (которая меньше, чем вся сама Checker Framework).

Ответ 2

Каждая аннотация имеет смысл!

javax.validation.constraints.NotNull

Эти значения определяются спецификацией валидации bean и используются для выполнения проверки, отличной от нуля, во время выполнения, поэтому ее необходимо сохранить во время выполнения для выполнения, например, valdiation формы...

@RetentionPolicy.SOURCE = > обычно используется для документации @RetentionPocily.class= > позволяет предоставить некоторую информацию компилятору, но не JVM (например, для генерации кода во время компиляции) @RetentionPolicy.RUNTIME = > позволяет получать информацию аннотации на уровне JVM (так что во время выполнения).

Привет,

Лоик