Java-лучший способ обнаружить NPE во время компиляции, когда не разрешено использовать аннотации @NotNull или @Nullable

я использовал много @NotNull/@Nullable аннотации, позволяющие IDE помочь мне узнать потенциал NPE во время компиляции. Однако моя новая команда не позволяет использовать @NotNull/@Nullable аннотации, а также пользовательские аннотации, такие как разрешенные. В результате я стал гораздо чаще писать ошибки, вызванные NPE чем раньше.

я пробовал несколько решений:

  1. использовать Optional<T> в java 8. Однако это не всегда хорошо. Это, как правило, не рекомендуется использовать Optional<T> как тип полей или аргументов. Это также очень расстраивает, что Optional<T> сам экземпляр может быть null. Кроме того, сложно управлять потоками управления внутри лямбда-выражений при вызове ifPresent(obj->...)(проще в Java 9). И используя слишком много Optional<T>s делает код немного многословен.(UPDATE: к сожалению,Optional<T> также запрещено использовать сейчас)
  2. сделать IDE рассматривать каждый необъявленный экземпляр как @Nullable. Это решение помогите мне выяснить некоторые потенциальные ошибки, однако IDE предложит мне проверить почти каждый вызов метода, что действительно раздражает, так как многие методы разработаны намеренно не возвращая null.
  3. проверьте все вызовы методов. Это жизнеспособное решение, однако оно имеет серьезное влияние, что возможность быть null будет передаваться везде через вызовы методов. При таких обстоятельствах каждый аргумент метода может быть null, и когда аргумент проверяется на nullity, метод обычно возвращает null непрерывно. Наконец, каждый метод "заражен" возможностью получения null Аргументы и возвращение null.
  4. вызов Objects.requireNonNull() чтобы предотвратить вышеупомянутую проблему. Это немного уменьшает боль проверки null везде. Однако это не гарантирует, что вызывающий абонент не передаст null в случаях, когда null Не допускается. И один раз null передано, время работы NPE thrown гораздо более вероятно, чтобы разрушить ваше приложение.
  5. переключиться на Котлин. Конечно, это не допускается:)

есть ли другие предложения об обнаружении NPE во время компиляции (и сохранении моей работы)? я думаю, что решение этой проблемы может быть широко использован не только помогаете себе, так как не все команды позволяют использование @NotNull/@Nullable аннотации Optional<T>s.

6 ответов


не окончательный ответ, но несколько способов исследовать:

  • инструменты findBug, PMD , Coverity ... довольно хороши в этом упражнении.
  • Проверьте причину, по которой вы не можете использовать аннотацию в своей команде. Может быть, вы сможете заставить свою команду передумать? (На то может быть и веская причина.)
  • в Eclipse IDE является reasonnably хорош в этом экзерсисе. Вы пробовали параметры в " Windows > настройки > Java > Компилятор > ошибки / предупреждения > нулевой анализ'?
  • модульное тестирование. Рассмотрим ситуацию "не должно произойти" в нескольких тестовых случаях. Инструменты покрытия кода (например,JaCoCo) может быть полезным, как wel.
  • оборонительное Программирование (простое утверждение "if", утверждения ...)
  • смесь предыдущих элементов

надеюсь, что это помогает.


вы не сказали, какую IDE вы используете, но Eclipse и Intellij поддерживают внешние аннотации. С их помощью вы все равно можете аннотировать свой код локально и предоставить IDE нулевой анализ.

Документация Intellij
Документация Eclipse


Я рекомендую проверить SonarLint, которая является очень хорошим инструментом для обнаружения всех видов ошибок и ошибок, в том числе NPE.


вы, вероятно, можете найти способ использовать Optional<T> это подходит для ваших случаев.

предположим, вы должны написать метод U doStuff(T param) и param дается вашему коду некоторой библиотекой от другого человека, и он может быть нулевым.

внутри тела метода doStuffможно сделать

return Optional.ofNullable(param)
       .map(notNullParam -> doThing(notNullParam))
       .orElse(null);

таким образом, вы уверены, что ваш Optionalсам по себе не null, люди все еще могут использовать ваш API с параметрами, которые являются null, и вы возвращаете null, когда это имеет смысл для их.


что вы должны сделать-это придумать хороший дизайн API и указать, какой из слоев разрешено возвращать null, а какой нет.

В общем, вы всегда должны пытаться вернуть что - то другое, а не пустую коллекцию, объект, представляющий not-found.

поэтому вы должны проверить наличие нулей вручную, где возврат может иметь смысл быть нулевым. В противном случае просто соберите, чтобы не возвращать null и просто не проверять.

вы также можете ввести некоторые методы утилиты для проверки нулевых / пустых коллекций:

Check.isEmpty() вернет true, если коллекция равна null или не равна null, но пуста и так далее...

вы также можете использовать нулевой объект шаблона


Я могу связать вашу проблему с моими вариантами использования. В этих случаях не стесняйтесь предлагать инструменты покрытия кода.

  • JaCoCo очень удобно. Если вы используете IntelliJ, встроенное покрытие кода Jacoco/IJ ясно дает вам нарушения и возможный NPE
  • тесты для поддержки Вашего домена мудрые ненулевые сценарии объектов

ведь NPE до сих пор дизайн, основанный/программист на основе вина. Держите код хорошо протестирован и правильных проверок, чтобы избежать NPE и бросить пользовательские исключения или IllegalArgumentException Если ваш сервис предполагает допустимое значение.