Как избежать нулевого предупреждения при использовании @NotNull и проверке нулевого значения в другом методе перед вызовом метода?

У меня есть немного сложная система проверки, которая в упрощенном виде выглядит примерно так:

private static void mainMethod(@Nullable String startParam, @Nullable String nextParam) {

    String nextStep = methodSelect(startParam, nextParam);

    switch (nextStep) {
        case "none":
            break;
        case "goFinal":
            finalMethod(startParam);
            break;
        case "goNext":
            nextMethod(nextParam);
            break;
    }
}

private static void nextMethod(@NotNull String nextParam) {
    System.out.println(nextParam);
}

private static void finalMethod(@NotNull String startParam) {
    System.out.println(startParam);
}

@NotNull
private static String methodSelect(@Nullable String startParam,@Nullable String nextParam) {
    if (startParam == null && nextParam == null) {
        return "none";
    } if (startParam == null) {
        return "goNext";
    } else {
        return "goFinal";
    }
}

Но я получаю предупреждения, когда в операторе switch, вызывающем как finalMethod(), так и nextMethod(), о том, что «Аргумент x может быть нулевым», даже несмотря на то, что methodSelect() и оператор switch впоследствии гарантируют, что эти аргументы не будут нулевыми. Как мне правильно избавиться от этих предупреждений, надеюсь, без повторной проверки на null в этих методах или перед ними? Спасибо!

Я использую IntelliJ IDEA 2016.3.4, Java 8 и аннотации:

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

person Herberts Markūns    schedule 07.02.2017    source источник


Ответы (1)


Это очень сложный код — вы имитируете отражение, чтобы вызывать разные методы в зависимости от тестов времени выполнения.

В IntelliJ IDEA вы захотите подавить предупреждение в IDE или с помощью аннотации кода.

Некоторые другие инструменты имеют более сложный анализ кода. Вот небольшой вариант вашего кода, который использует логическое значение вместо строки, чтобы указать, какой метод вызывать. Проверка на наличие ошибок в Checker Framework может проверить безопасность этого кода на наличие ошибок, благодаря аннотации постусловия @EnsuresNonNullIf.

import org.checkerframework.checker.nullness.qual.*;

class Example {

  private static void mainMethod(@Nullable String startParam, @Nullable String nextParam) {

    if (! useFinal(startParam)) {
      // do nothing
    } else {
      finalMethod(startParam);
    }
  }

  private static void nextMethod(@NonNull String nextParam) {
    System.out.println(nextParam);
  }

  private static void finalMethod(@NonNull String startParam) {
    System.out.println(startParam);
  }

  @EnsuresNonNullIf(expression="#1", result=true)
  private static boolean useFinal(@Nullable String startParam) {
    if (startParam == null) {
      return false;
    } else {
      return true;
    }
  }

}

Аннотация @EnsuresNonNullIf в настоящее время не обрабатывает строки, используемые в исходном коде; вы можете запросить такое расширение у сопровождающих или реализовать его самостоятельно и отправить запрос на включение.

person mernst    schedule 08.02.2017
comment
Спасибо за отличный ответ! - person Herberts Markūns; 10.02.2017