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
, если ваша служба ожидает действительное значение.