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

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

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

  • Используйте Optional<T> в java 8. Однако это не подходит для каждого случая. Обычно не рекомендуется использовать Optional<T> как тип полей или аргументов. Также очень огорчает, что сам экземпляр Optional<T> может быть null. Кроме того, трудно управлять потоками управления внутри лямбда-выражений при вызове ifPresent(obj->...) (это проще в Java 9). И использование слишком большого числа Optional<T> делает код немного подробным. (UPDATE: К сожалению, Optional<T> также запрещено использовать сейчас)
  • Сделайте IDE обработкой каждого unannotated экземпляра как @Nullable. Это решение помогает мне выявить некоторые возможные ошибки, однако IDE предложит мне проверить почти все вызовы методов, что очень раздражает, поскольку многие методы предназначены намеренно не возвращать null.
  • Проверить все вызовы методов. Это жизнеспособное решение, однако оно оказывает сильное влияние на то, что возможность null будет проходить везде через вызовы методов. В таких обстоятельствах каждый аргумент метода может быть null, и когда аргумент проверяется на nullity, метод обычно возвращает a null непрерывно. Наконец, каждый метод "заражен" возможностью получения аргументов null и возврата null.
  • Вызовите Objects.requireNonNull(), чтобы предотвратить возникшую проблему. Это немного уменьшает боль во время проверки null. Однако он не гарантирует, что вызывающий абонент не передаст null в случаях, когда null не разрешено. И как только null будет передано, запущенная среда NPE будет гораздо более подвержена разрушению вашего приложения.
  • Переключитесь на kotlin. Конечно, это не разрешено:)

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

Ответы

Ответ 1

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

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

Надеюсь, что это поможет.

Ответ 2

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

Интеллектуальная документация
Документация Eclipse

Ответ 3

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

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

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

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

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

Ответ 4

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

Ответ 5

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

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

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

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

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

Вы также можете использовать шаблон null-object

Ответ 6

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

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

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