#java #intellij-idea #nullpointerexception #intellij-inspections
#java #intellij-idea #исключение nullpointerexception #intellij-инспекции
Вопрос:
Обычно я сталкиваюсь со следующей проверкой IntelliJ
private boolean bar() {
return foo().contains("foo"); // Method invocation 'contains' may produce 'java.lang.NullPointerException'
}
private String foo() {
return null;
}
Проверки кажутся мне нормальными, но одно из (или часто единственное) предлагаемых исправлений от IntelliJ заключается в следующем:
private boolean bar() {
return Objects.requireNonNull(foo()).contains("foo");
}
После этого предупреждение исчезает. Но я вообще не понимаю, как это помогает? requireNonNull
просто выдаст то же самое, NullPointerException
что было бы выдано в любом случае при .contains
вызове на null
.
Обычно IntelliJ делает значимые предложения, и это распространенное, так что я упускаю суть здесь?
Комментарии:
1. Я согласен, что предлагаемое решение не лучше, чем сама проблема.
2. Я думаю, что предложение здесь бессмысленно, потому что вы получаете объект и немедленно используете его. Это более осмысленно, если вы получаете объект в одном месте и разыменование в другом. Таким образом, исключение будет сгенерировано раньше, что лучше. Это все еще звучит неразумно.
3. Я согласен. Решение в любом случае предоставит вам NPE 🙂
Ответ №1:
Обоснование использования Objects#requireNonNull
аналогично тому, что стоит за возвратом Optional
: вы делаете это, чтобы управлять ожиданиями.
- Когда вы возвращаете,
Optional<Something>
вместо того, чтобы простоSomething
сказать: «Эй, я знаю, что этоSomething
значение может отсутствовать, поэтому вместо того, чтобы возвращатьnull
и позволять вам угадывать, я возвращаюOptional<Something>
вместо этого, чтобы дать понять, что вам следует ожидать, что его там может не быть, и что я ожидаю, что вы проверите, есть ли оно там, прежде чем использовать его «. - Когда вы вызываете
Objects.requireNonNull(something)
в своем коде перед использованиемsomething
, вы говорите: «Эй, если вы читаете это, я просто хотел, чтобы вы знали, что я ожидаю, что этотsomething
параметр не будет null, и что я ожидаю, что вы убедитесь, что это не так, прежде чем вызывать этот код; поэтому вместо того, чтобы просто доверять вам и напрямую вызыватьsomething.contains(...)
, я вызываюrequireNonNull
прямо здесь и сейчас, чтобы прояснить это (в случае каких-либо из нас пропустили@NotNull
аннотацию в объявлении метода).»
Решает ли это проблему? Нет, это не так. IntelliJ не может волшебным образом запретить параметру принимать значение null. Но это может заставить любого, кто читает этот код, знать, что параметр не должен быть нулевым, и рассуждать о сценариях, в которых это может произойти.
Комментарии:
1. Как разработчик IntelliJ IDEA, ответственный за эту подсистему, я подтверждаю, что этот ответ правильный. В целом идея заключается в том, что
foo()
, вероятно, может возвращать null в другом месте, но в данном конкретном контексте я заявляю, что этого не должно происходить. Это лучший способ избежать предупреждения, чем подавления.