Я пытаюсь сделать мой код более читабельным, а также использовать такие инструменты, как проверка кода IDE и / или статический анализ кода (FindBugs и Sonar), чтобы избежать исключений NullPointerException. Многие инструменты кажутся несовместимыми с @NotNull
/ @NonNull
/ @Nonnull
аннотациями друг друга, и перечисление их всех в моем коде было бы ужасно читать. Какие-нибудь предложения, какой из них является «лучшим»? Вот список эквивалентных аннотаций, которые я нашел:
javax.validation.constraints.NotNull
Создан для проверки во время выполнения, а не для статического анализа.
документацияedu.umd.cs.findbugs.annotations.NonNull
Используется FindBugs статического анализа и , следовательно , эхолота (теперь Sonarqube )
документацииjavax.annotation.Nonnull
Это может работать и с Findbugs, но JSR-305 неактивен. (См. Также: Каков статус JSR 305? ) Источникorg.jetbrains.annotations.NotNull
Используется IntelliJ IDEA IDE для статического анализа.
документацияlombok.NonNull
Используется для управления генерацией кода в Project Lombok .
Заполнение аннотации, так как нет стандарта.
источник , документацияandroid.support.annotation.NonNull
Аннотация для маркеров, доступная в Android, предоставляется документацией пакета support-annotations
org.eclipse.jdt.annotation.NonNull
Используется Eclipse , для анализа статического кода
документации
com.sun.istack.internal.NotNull
. OMG ...Ответы:
Начиная с JSR 305 (целью которого было стандартизировать
@NonNull
и@Nullable
) была неактивной в течение нескольких лет, я боюсь, что нет хорошего ответа. Все, что мы можем сделать, это найти прагматическое решение, и мое следующее:Синтаксис
С чисто стилистической точки зрения я хотел бы избегать любых ссылок на IDE, фреймворк или любой инструментарий, кроме самой Java.
Это исключает:
android.support.annotation
edu.umd.cs.findbugs.annotations
org.eclipse.jdt.annotation
org.jetbrains.annotations
org.checkerframework.checker.nullness.qual
lombok.NonNull
Что оставляет нас с
javax.validation.constraints
илиjavax.annotation
. Бывший поставляется с JEE. Если это лучше, чемjavax.annotation
, что может в конечном итоге прийти с JSE или вообще никогда, это вопрос дискуссии. Я лично предпочитаюjavax.annotation
потому что я не хотел бы зависимость JEE.Это оставляет нас с
javax.annotation
который также самый короткий.
Существует только один синтаксис, который был бы даже лучше:
java.annotation.Nullable
. Как закончили другие пакеты отjavax
доjava
в прошлом, javax.annotation было бы шагом в правильном направлении.Реализация
Я надеялся, что у них у всех одинаковая тривиальная реализация, но подробный анализ показал, что это не так.
Сначала за сходство:
Все
@NonNull
аннотации имеют строкукроме
org.jetbrains.annotations
который называет это@NotNull
и имеет тривиальную реализациюjavax.annotation
который имеет более длительную реализациюjavax.validation.constraints
который также называет это@NotNull
и имеет реализациюВсе
@Nullable
аннотации имеют строкукроме (опять же)
org.jetbrains.annotations
с их тривиальной реализацией.Для различий:
Поразительным является то, что
javax.annotation
javax.validation.constraints
org.checkerframework.checker.nullness.qual
у всех есть аннотации времени выполнения (
@Retention(RUNTIME)
), в то время какandroid.support.annotation
edu.umd.cs.findbugs.annotations
org.eclipse.jdt.annotation
org.jetbrains.annotations
только время компиляции (
@Retention(CLASS)
).Как описано в этом ответе SO, влияние аннотаций времени выполнения меньше, чем можно подумать, но они имеют преимущество, заключающееся в том, что они позволяют инструментам выполнять проверки во время выполнения в дополнение к проверкам времени компиляции.
Другое важное отличие состоит в том, где в коде могут использоваться аннотации. Есть два разных подхода. Некоторые пакеты используют контексты стиля JLS 9.6.4.1. Следующая таблица дает обзор:
org.eclipse.jdt.annotation
,javax.annotation
Иorg.checkerframework.checker.nullness.qual
использовать контексты , определенные в JLS 4.11, что на мой взгляд, правильный способ сделать это.Это оставляет нас с
javax.annotation
org.checkerframework.checker.nullness.qual
в этом раунде.
Код
Чтобы помочь вам сравнить дальнейшие детали, я перечислю код каждой аннотации ниже. Чтобы упростить сравнение, я удалил комментарии, импорт и
@Documented
аннотацию. (все они были@Documented
за исключением классов из пакета Android). Я изменил порядок строк и@Target
полей и нормализовал квалификации.Для полноты, вот
@Nullable
реализации:Следующие два пакета не имеют
@Nullable
, поэтому я перечислю их отдельно; Ломбок довольно скучный@NonNull
. В на самом деле и имеет длинноватые реализацию.javax.validation.constraints
@NonNull
@NotNull
Служба поддержки
Из моего опыта,
javax.annotation
по крайней мере, поддерживается Eclipse и Checker Framework из коробки.Резюме
Моей идеальной аннотацией был бы
java.annotation
синтаксис с реализацией Checker Framework.Если вы не собираетесь использовать Checker Framework, то
javax.annotation
( JSR-305 ) пока что остается лучшим выбором.Если вы готовы покупать в Checker Framework, просто используйте их
org.checkerframework.checker.nullness.qual
.источники
android.support.annotation
отandroid-5.1.1_r1.jar
edu.umd.cs.findbugs.annotations
отfindbugs-annotations-1.0.0.jar
org.eclipse.jdt.annotation
отorg.eclipse.jdt.annotation_2.1.0.v20160418-1457.jar
org.jetbrains.annotations
отjetbrains-annotations-13.0.jar
javax.annotation
отgwt-dev-2.5.1-sources.jar
org.checkerframework.checker.nullness.qual
отchecker-framework-2.1.9.zip
lombok
отlombok
коммитаf6da35e4c4f3305ecd1b415e2ab1b9ef8a9120b4
javax.validation.constraints
отvalidation-api-1.0.0.GA-sources.jar
источник
javax.annotation
является то, что он а) основан на мертвой JSR, б) трудно найти артефакт, который просто предоставляет аннотации и поддерживается. Один из findbugs не является: search.maven.org/…javax.annotation
- это вызывает проблемы с Java 9, потому что другие модули также предоставляют классы в этом пакете (jax-ws).javax.annotation.NonNull
, так и не был завершен, потому что его спецификационный лидер вышел из AWOL Это не имело никакого отношения к решению Oracle.Мне очень нравится Checker Framework , представляющий собой реализацию аннотаций типов ( JSR-308 ), которая используется для реализации средств проверки дефектов, таких как средство проверки на нулевое значение. На самом деле я не пробовал других предлагать какое-либо сравнение, но я доволен этой реализацией.
Я не связан с группой, которая предлагает программное обеспечение, но я фанат.
Четыре вещи, которые мне нравятся в этой системе:
У него есть дефекты для проверки на нулевое значение (@Nullable), но также есть и для неизменяемости и интернирования (и других). Я использую первое (нулевое значение) и пытаюсь использовать второе (неизменность / IGJ). Я пробую третий, но пока не уверен, что буду использовать его в долгосрочной перспективе. Я еще не убежден в общей полезности других средств проверки, но приятно знать, что сама структура представляет собой систему для реализации множества дополнительных аннотаций и средств проверки.
Настройка по умолчанию для проверки на нулевое значение работает хорошо: ненулевое значение, кроме локальных (NNEL). В основном это означает, что по умолчанию средство проверки обрабатывает все (переменные экземпляра, параметры метода, универсальные типы и т. Д.), За исключением локальных переменных, как если бы они имели тип @NonNull по умолчанию. Согласно документации:
Вы можете установить другое значение по умолчанию для класса или для метода, если NNEL не работает для вас.
Этот каркас позволяет вам использовать его без создания зависимости от каркаса , заключив свои комментарии в комментарий: например
/*@Nullable*/
. Это хорошо, потому что вы можете аннотировать и проверять библиотеку или общий код, но при этом иметь возможность использовать эту библиотеку / общий код, закодированный в другом проекте, который не использует платформу. Это хорошая особенность. Я привык к его использованию, хотя сейчас я имею тенденцию включать Checker Framework во всех моих проектах.Фреймворк позволяет аннотировать используемые вами API-интерфейсы , которые еще не аннотированы для нулевых значений, с помощью заглушек.
источник
Я использую тот IntelliJ, потому что меня больше всего интересует то, что IntelliJ помечает вещи, которые могут создавать NPE. Я согласен, что расстраивает отсутствие стандартной аннотации в JDK. Говорят о его добавлении, он может превратиться в Java 7. В таком случае будет еще один на выбор!
источник
javax.annotation.Nonnull
более широко принят, не так ли?Согласно списку возможностей Java 7 аннотации типа JSR-308 откладываются до Java 8. Аннотации JSR-305 даже не упоминаются.
Немного информации о состоянии JSR-305 в приложении к последней версии JSR-308. Это включает в себя наблюдение, что аннотации JSR-305 кажутся заброшенными. Страница JSR-305 также показывает его как «неактивный».
В то же время, прагматический ответ - использовать типы аннотаций, поддерживаемые наиболее широко используемыми инструментами ... и быть готовым изменить их, если ситуация изменится.
Фактически, JSR-308 не определяет какие-либо типы / классы аннотаций, и похоже, что они думают, что это выходит за рамки. (И они правы, учитывая существование JSR-305).
Однако, если JSR-308 действительно выглядит как превращение в Java 8, меня не удивит, если интерес к JSR-305 возродится. AFAIK, команда JSR-305 официально не отказалась от своей работы. Они просто молчали 2+ года.
Интересно, что Билл Пью (технический лидер JSR-305) - один из тех, кто стоит за FindBugs.
источник
Для проектов Android вы должны использовать
android.support.annotation.NonNull
иandroid.support.annotation.Nullable
. Эти и другие полезные аннотации для Android доступны в библиотеке поддержки .С http://tools.android.com/tech-docs/support-annotations :
источник
javax.annotation.*
аннотациямиЕсли кто-то просто ищет классы IntelliJ: вы можете получить их из репозитория maven с помощью
источник
JSR305 и FindBugs созданы одним и тем же человеком. Оба плохо обслуживаются, но являются стандартными и поддерживаются всеми основными IDE. Хорошей новостью является то, что они работают хорошо, как есть.
Вот как применить @Nonnull ко всем классам, методам и полям по умолчанию. См. Https://stackoverflow.com/a/13319541/14731 и https://stackoverflow.com/a/9256595/14731.
@NotNullByDefault
2. Добавьте аннотацию к каждому пакету:
package-info.java
ОБНОВЛЕНИЕ : По состоянию на 12 декабря 2012 года JSR 305 числится как «неактивный». Согласно документации:
Похоже , JSR 308 является превращение его в JDK 8 , и хотя JSR не определяет @NotNull, сопровождающий
Checkers Framework
делает. На момент написания этой статьи плагин Maven не работал из-за этой ошибки: https://github.com/typetools/checker-framework/issues/183источник
Различают статический анализ и анализ времени выполнения. Используйте статический анализ для внутренних вещей и анализ времени выполнения для открытых границ вашего кода.
Для вещей, которые не должны быть нулевыми:
Проверка во время выполнения: используйте «if (x == null) ...» (нулевая зависимость) или @ javax.validation.NotNull (с проверкой bean-компонента) или @ lombok.NonNull (простой и простой) или guavas Preconditions.checkNotNull (.. .)
Статическая проверка: используйте аннотацию @NonNull
Это должно дать наилучший результат: предупреждения в среде IDE, ошибки от Findbugs и checkerframework, значимые исключения во время выполнения.
Не ожидайте, что статические проверки станут зрелыми, их имена не стандартизированы, а разные библиотеки и IDE обрабатывают их по-разному, игнорируют их. Классы JSR305 javax.annotations. * Выглядят как стандартные, но это не так, и они вызывают разделение пакетов с Java9 +.
Некоторые примечания к объяснениям:
До Java9 это моя рекомендация:
Обратите внимание, что нет способа заставить Spotbugs выдавать предупреждение при разыменовании параметра метода, допускающего значение NULL (на момент написания, версия 3.1 Spotbugs). Может быть, проверочная схема может сделать это.
К сожалению, эти аннотации не делают различий между случаями открытого метода библиотеки с произвольными местами вызова и непубличными методами, в которых может быть известен каждый из них. Таким образом, двойное значение: «Укажите, что null нежелателен, но, тем не менее, подготовьтесь к тому, что null будет передан», невозможно в одном объявлении, поэтому в приведенном выше примере есть разные аннотации для интерфейса и реализации.
Для случаев, когда подход с разделенным интерфейсом не практичен, следующий подход является компромиссом:
Это помогает клиентам не передавать ноль (писать правильный код), возвращая при этом полезные ошибки, если они это делают.
источник
Eclipse также имеет свои аннотации.
Смотрите подробности на http://wiki.eclipse.org/JDT_Core/Null_Analysis .
источник
Просто отметим, что Java Validation API (
javax.validation.constraints.*
) не поставляется с@Nullable
аннотацией, что очень ценно в контексте статического анализа. Это имеет смысл для проверки bean-компонента во время выполнения, поскольку это значение по умолчанию для любого не примитивного поля в Java (т. Е. Ничего для проверки / применения). Для заявленных целей следует взвесить альтернативы.источник
К сожалению,
JSR 308
не добавит больше значений, чем этот проект локального предложения Not Null здесьJava 8
не будет поставляться с единственной аннотацией по умолчанию или собственнойChecker
структурой. Подобный Find-Bugs илиJSR 305
, этот JSR плохо обслуживается небольшой группой в основном академических команд.Нет коммерческой силой , стоящей за ним, таким образом ,
JSR 308
запускиEDR 3
(Early не проект обзора вJCP
) сейчас, в то время какJava 8
предполагается грузить менее чем за 6 месяцев: -О Подобно310
кстати. но в отличие от того,308 Oracle
что взял на себя ответственность за это сейчас, от его основателей, чтобы минимизировать вред, который он нанесет платформе Java.Каждый проект, поставщик и академический класс, подобные тем, которые стоят за,
Checker Framework
иJSR 308
создадут собственную проприетарную аннотацию проверки.Делать исходный код несовместимым на долгие годы, пока не будут найдены несколько популярных компромиссов и, возможно, добавлены в
Java 9
или10
, или через фреймворки, такие какApache Commons
илиGoogle Guava
;-)источник
Android
Этот ответ зависит от Android. Android имеет пакет поддержки под названием
support-annotations
. Это предоставляет десятки специфических для Android аннотаций, а также предоставляет общие, такие какNonNull
,Nullable
т. Д.Чтобы добавить пакет support-annotations , добавьте следующую зависимость в ваш build.gradle:
а затем используйте:
источник
В ожидании того, что это будет рассмотрено вверх по течению (Java 8?), Вы также можете просто определить свой собственный локальный проект
@NotNull
и@Nullable
аннотации. Это может быть полезно также в случае, если вы работаете с Java SE, где по умолчаниюjavax.validation.constraints
недоступно .По общему признанию это было бы в значительной степени для декоративных или перспективных целей, поскольку вышеупомянутое, очевидно, само по себе не добавляет поддержки статическому анализу этих аннотаций.
источник
Если вы разрабатываете для Android, вы несколько связаны с Eclipse (редактировать: на момент написания, больше нет), который имеет свои собственные аннотации. Он включен в Eclipse 3.8+ (Juno), но по умолчанию отключен.
Вы можете включить его в «Предпочтения»> «Java»> «Компилятор»> «Ошибки / предупреждения»> «Нулевой анализ» (сворачиваемый раздел внизу).
Установите флажок «Включить нулевой анализ на основе аннотаций»
http://wiki.eclipse.org/JDT_Core/Null_Analysis#Usage содержит рекомендации по настройке. Однако, если у вас есть внешние проекты в вашей рабочей области (например, SDK facebook), они могут не соответствовать этим рекомендациям, и вы, вероятно, не хотите исправлять их при каждом обновлении SDK ;-)
Я использую:
источник
@chaqke
.Если вы работаете над большим проектом, возможно, вам лучше создавать свои собственные
@Nullable
и / или@NotNull
аннотации.Например:
Если вы используете правильную политику хранения , аннотации не будут доступны во время выполнения . С этой точки зрения это просто внутренняя вещь.
Несмотря на то, что это не строгая наука, я думаю, что имеет смысл использовать для нее внутренний класс.
@Nullable
/@NotNull
аннотации.Дополнительные вопросы (см. Комментарии):
Как настроить это в IntelliJ?
источник
idea
ничего не говорят оvoid test(@NonNull String s) {}
называютtest(null);
Здесь уже слишком много ответов, но (а) сейчас 2019 год, и до сих пор нет «стандарта»
Nullable
и (б) нет других ответов, ссылающихся на Котлина.Ссылка на Kotlin важна, потому что Kotlin на 100% совместим с Java и имеет базовую функцию нулевой безопасности. При вызове библиотек Java можно воспользоваться этими аннотациями, чтобы сообщить инструментам Kotlin, может ли API-интерфейс Java принимать или возвращать
null
.Насколько я знаю, единственными
Nullable
пакетами, совместимыми с Kotlin, являютсяorg.jetbrains.annotations
иandroid.support.annotation
(сейчасandroidx.annotation
). Последний совместим только с Android, поэтому его нельзя использовать в проектах JVM / Java / Kotlin, отличных от Android. Тем не менее, пакет JetBrains работает везде.Поэтому, если вы разрабатываете пакеты Java, которые также должны работать в Android и Kotlin (и поддерживаться Android Studio и IntelliJ), ваш лучший выбор, вероятно, - пакет JetBrains.
Maven:
Gradle:
источник
Есть еще один способ сделать это в Java 8. Я делаю 2 вещи, чтобы выполнить то, что мне нужно:
java.util.Optional
java.util.Objects.requireNonNull
Пример:
Так что мой вопрос, нужно ли нам даже комментировать при использовании Java 8?
Изменить: Позже я узнал, что некоторые считают плохую практику для использования
Optional
в аргументах, здесь есть хорошая дискуссия с плюсами и минусами Почему Java 8 необязательно не использовать в аргументахАльтернативный вариант, учитывая, что не рекомендуется использовать Optional в аргументах, нам нужно 2 конструктора:
источник
new Role(null,null,null,null);
. С аннотациями мой IDE и статический анализ будут предупреждать, что в эти параметры нельзя передать нуль. Без этого я не узнаю, пока не выполню код. Это ценность аннотаций.description
не нулевым, и клиентский код мог бы передать пустую строку, но во многих случаях было бы удобно различать пустую строку и не иметь значения. Спасибо за ваш комментарий. Я обновлю ответ.Разве у Солнца нет своего? Что это:
http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Modules-com.sun/istack/com.sun.istack.internal.htm
Это, кажется, упаковано со всеми версиями Java, которые я использовал в течение прошлых нескольких лет.
Изменить: как уже упоминалось в комментариях ниже, вы, вероятно, не хотите использовать их. В этом случае мой голос за аннотации IntelliJ Jetbrains!
источник
Одно из преимуществ IntelliJ заключается в том, что вам не нужно использовать их аннотации. Вы можете написать свой собственный или использовать любой другой инструмент, который вам нравится. Вы даже не ограничены одним типом. Если вы используете две библиотеки, которые используют разные аннотации @NotNull, вы можете указать IntelliJ использовать обе из них. Для этого перейдите в «Настроить проверки», нажмите «Постоянные условия и исключения» и нажмите кнопку «Настроить проверки». Я использую Nullness Checker везде, где могу, поэтому я настроил IntelliJ для использования этих аннотаций, но вы можете заставить его работать с любым другим инструментом, который вам нужен. (У меня нет мнения о других инструментах, потому что я использую проверки IntelliJ в течение многих лет, и я люблю их.)
источник
Другой вариант заключается в аннотации , снабженный ANTLR 4. После Прицепных Request # 434 , артефакт , содержащий
@NotNull
и@Nullable
аннотацию включает в себя процессор , который производит аннотации ошибок и / или предупреждения во время компиляции в одном событии из этих атрибутов неправильно (например, если оба применяются к одному и тому же элементу, или если@Nullable
применяются к элементу с примитивным типом). Процессор аннотаций обеспечивает дополнительную гарантию в процессе разработки программного обеспечения, что информация, передаваемая с помощью этих аннотаций, является точной, в том числе в случаях наследования методов.источник
Если вы создаете свое приложение с использованием Spring Framework, я бы предложил использовать
javax.validation.constraints.NotNull
Coming from Beans Validation, упакованный в следующую зависимость:Основным преимуществом этой аннотации является то, что Spring обеспечивает поддержку как параметров метода, так и полей класса, помеченных как
javax.validation.constraints.NotNull
. Все, что вам нужно сделать, чтобы включить поддержку:поставьте jar api для проверки bean-компонентов и jar с реализацией валидатора аннотаций jsr-303 / jsr-349 (который поставляется с зависимостью Hibernate Validator 5.x):
предоставить MethodValidationPostProcessor для контекста Spring
наконец, вы аннотируете ваши классы Spring,
org.springframework.validation.annotation.Validated
и Spring будет автоматически обрабатывать валидацию.Пример:
Когда вы пытаетесь вызвать метод doSomething и передать значение null в качестве значения параметра, пружина (с помощью HibernateValidator) сработает
ConstraintViolationException
. Нет необходимости в ручной работе здесь.Вы также можете проверить возвращаемые значения.
Еще одно важное преимущество использования
javax.validation.constraints.NotNull
Beans Validation Framework заключается в том, что на данный момент он все еще разрабатывается и для новой версии 2.0 запланированы новые функции.Как насчет
@Nullable
? Ничего подобного в Beans Validation 1.1 нет. Что ж, я могу поспорить, что если вы решите использовать, то@NotNull
все, что НЕ аннотировано,@NonNull
эффективно «обнуляется», поэтому@Nullable
аннотация бесполезна.источник
Spring 5 имеет @NonNullApi на уровне пакета. Это кажется удобным выбором для проекта, который уже имеет зависимости Spring. Все поля, параметры и возвращаемые значения по умолчанию @NonNull и @Nullable могут быть применены в нескольких местах, которые отличаются.
Файл package-info.java:
https://docs.spring.io/spring-data/commons/docs/current/reference/html/#repositories.nullability.annotations
источник