Улучшение проверки кода Intellij для может выдавать предупреждения NullPointerException - PullRequest
2 голосов
/ 03 марта 2020

У меня есть класс с функцией hasField, которая проверяет, присутствует ли поле и не является ли оно пустым, и функцией getField, которая возвращает значение поля (или ноль, если ее нет).

В моем коде, когда я вызываю getField сразу после проверки hasField, я знаю, что getField не будет возвращать ноль, но проверка IDE ( Постоянные условия и исключения ) этого не знает. Я получаю набор методов method name, которые могут выдать NullPointerException

Я пытаюсь найти чистый способ убрать это предупреждение go.

Обходные пути

Вот некоторые обходные пути, которые я мог бы сделать, но я нахожу все эти хакеры:

  1. Surround getField с Objects.requireNotnull, код будет недоступен. Я бы предпочел не делать этого, поскольку это делает код немного менее читабельным.
  2. Подавляет предупреждения, если я знаю, что это безопасно. Опять же, не является предпочтительным, поскольку это произойдет в нескольких местах нашего кода.
  3. Игнорировать предупреждения. В этом случае мы можем пропустить le git предупреждений только потому, что раздел предупреждений будет слишком шумным.

Идеальное решение

Смогу ли я каким-то образом установить составить предупреждение таким образом, что если hasField истинно, то getField вернет ненулевое значение? Я изучил Комментарии к контракту JetBrains , но выполнение того, что я хочу, похоже, выходит за рамки того, что поддерживается @ Contract

Пример кода

Вот Пример минимального рабочего кода, который демонстрирует проблему:

import javax.annotation.Nullable;

public class Hello {

  private Hello(){}
  public static void main(String[] args) {
    TestClass test1 = new TestClass(null);
    if (test1.hasSample()) {
      System.out.println(test1.getSample().equals("abc"));
    }
 }
}

class TestClass {
  private final String sample;

  TestClass(String field) { this.sample = field; }

  boolean hasSample() { return sample != null; }

  @Nullable public String getSample() { return sample; }
}

Я получаю следующее предупреждение

Вызов метода equals может привести к NullPointerException

В идеале я бы хотел сказать IDE, что getSample не равно NULL, когда hasSample равно true.

1 Ответ

2 голосов
/ 04 марта 2020

Раскрытие информации Я являюсь разработчиком IntelliJ IDEA и отвечаю за эту подсистему


Нет, сейчас это невозможно. Нет лучшего решения, чем возможные обходные пути, которые вы уже перечислили, при условии, что вы не можете изменить API. Самое близкое, что у нас есть, - это использование очень тривиальных методов. Однако это работает только в том случае, если:

  • Методы, подобные hasSample() и getSample(), вызываются из одного класса
  • Вызываемые методы не могут быть переопределены (private / static / final / объявлено в финальном классе)

Например, эта функция работает в следующем коде:

final class TestClass { // if final is removed, the warning will appear again
  private final String sample;

  TestClass(String field) { this.sample = field; }

  boolean hasSample() { return sample != null; }

  @Nullable
  public String getSample() { return sample; }

  @Override
  public String toString() {
    if (hasSample()) {
      return "TestClass: "+getSample().trim(); // no warning on trim() invocation here
    }
    return "TestClass";
  }
}

На данный момент я могу только предложить рефакторинг ваших API для Optionals, как это:

import java.util.Optional;

public class Hello {

  private Hello(){}
  public static void main(String[] args) {
    TestClass test1 = new TestClass(null);
    test1.getSample().ifPresent(s -> System.out.println(s.equals("abc")));
    // or fancier: test1.getSample().map("abc"::equals).ifPresent(System.out::println);
  }
}

final class TestClass {
  private final String sample;

  TestClass(String field) { this.sample = field; }

  public Optional<String> getSample() { return Optional.ofNullable(sample); }
}
...