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

Аннотации типов Java 8 (JSR 308) позволяют средствам проверки типов выполнять статический анализ кода. Например, 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 только для того, чтобы избежать зависимостей во время выполнения, кажется грязным взломом.


person MyKey_    schedule 16.08.2016    source источник


Ответы (2)


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

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

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

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

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

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

person mernst    schedule 16.08.2016
comment
Связанное примечание для имитации аннотированных классов с помощью mockito (версия 2.2.0): хотя RetentionPolicy.RUNTIME означает, что аннотация, присутствующая в двоичном файле, не обязательно должна быть доступна во время выполнения, bugs.openjdk.java.net/browse/JDK-8152174 вызывает исключение NullPointerException в Java 8 при имитации аннотированного класса, для которого аннотация недоступен в пути к классам. - person MyKey_; 12.10.2016

Каждая аннотация имеет свое назначение!

javax.validation.constraints.NotNull

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

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

С уважением,

Loïc

person loicmathieu    schedule 16.08.2016
comment
Да, javax.validation.constraints.NotNull предназначен для выполнения. Но javax.annotation.Nonnull и org.checkerframework.checker.nullness.qual.NonNull не имеют цели во время выполнения IMO. - person MyKey_; 16.08.2016
comment
На ваш вопрос нет глобального ответа, создатель аннотации должен определить, нужно ли ее сохранять во время выполнения или нет. См. этот поток SOW для получения подсказки: /14810030/ - person loicmathieu; 16.08.2016