@ Сохранение аннотаций проверки типов Java
Аннотации типов Java 8 (JSR 308) позволяют средствам проверки типов выполнять статический анализ кода. Например, https://checkerframework.org/ может проверять возможную пустоту с помощью @NonNull
аннотаций.
Различные проекты определяют свои собственные аннотации NonNull, например:
org.checkerframework.checker.nullness.qual.NonNull
edu.umd.cs.findbugs.annotations.NonNull
javax.annotation.Nonnull
javax.validation.constraints.NotNull
lombok.NonNull
org.eclipse.jdt.annotation.NonNull
- и т. д. (см. Руководство по Checker Framework, раздел 3.7)
Для таких аннотаций я бы ожидал @interface
иметь @Retention(RetentionPolicy.CLASS)
потому что они обычно не нужны во время выполнения. Самое главное, что код не имеет каких-либо зависимостей времени выполнения от соответствующей библиотеки.
В то время как org.eclipse.jdt.annotation.NonNull
следует этому подходу, большинство других ненулевых аннотаций, таких как javax.annotation.Nonnull
(JSR 305) и org.checkerframework.checker.nullness.qual.NonNull
сам, есть @Retention(RetentionPolicy.RUNTIME)
, Есть ли какая-то конкретная причина для RetentionPolicy.RUNTIME
в этих аннотациях?
Пояснение: Checker Framework поддерживает аннотации в комментариях для обратной совместимости. Тем не менее, использование их в Java 8 просто для того, чтобы избежать зависимостей во время выполнения, кажется грязным хаком.
2 ответа
Это хороший вопрос.
Для статической проверки во время компиляции, CLASS
удержание будет достаточно. Обратите внимание, что SOURCE
сохранение будет недостаточным из-за отдельной компиляции: при проверке типа класса компилятору необходимо прочитать аннотации к библиотекам, которые он использует, а отдельно скомпилированные библиотеки доступны компилятору только в виде файлов классов.
Дизайнеры аннотаций использовали RUNTIME
сохранение, чтобы позволить инструментам выполнять операции во время выполнения. Это может включать проверку аннотаций (например, утверждение assert), проверку типов динамически загружаемого кода, проверку приведений и instanceof
операции, разрешение отражения более точно и многое другое. Сегодня таких инструментов не так много, но разработчики аннотаций хотели разместить их в будущем.
Вы отметили это с @Retention(RetentionPolicy.CLASS)
, "код не имеет никаких зависимостей во время выполнения от соответствующей библиотеки". Это на самом деле верно с @Retention(RetentionPolicy.RUNTIME)
, тоже! Посмотрите этот вопрос переполнения стека: Почему пропущенная аннотация не вызывает ClassNotFoundException во время выполнения?,
В итоге, используя CLASS
Хранение требует незначительного объема пространства во время выполнения, обеспечивает более потенциальное использование в будущем и не вводит зависимость во время выполнения.
В случае Checker Framework, он предлагает тесты во время выполнения, такие как isRegex(String)
, Если ваш код использует такие методы, ваш код будет зависеть от библиотеки времени выполнения Checker Framework (которая меньше, чем вся Checker Framework).
У каждой аннотации есть своя цель!
javax.validation.constraints.NotNull
Это определяется спецификацией проверки bean-компонента и используется для выполнения ненулевой проверки во время выполнения, поэтому ее необходимо сохранить во время выполнения для выполнения, например, проверки формы...
@ RetentionPolicy.SOURCE => обычно используется для документации @RetentionPocily.CLASS => позволяет предоставлять некоторую информацию компилятору, но не JVM (например, для выполнения генерации кода во время компиляции) @RetentionPolicy.RUNTIME => позволяет получать информацию аннотации на уровне JVM (так во время выполнения).
С Уважением,
Лоик