Проверка IntelliJ: ‘Вызов метода может привести к исключению NullPointerException’. Имеет ли смысл предлагаемое исправление?

#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 в другом месте, но в данном конкретном контексте я заявляю, что этого не должно происходить. Это лучший способ избежать предупреждения, чем подавления.