在方法中检查可空变量是否为空但未被识别

Nullable variable is checked for null in method but not recognized

我正在使用 IntelliJ IDEA 的代码检查来评估 @Nullable 注释。目前我正在使用 org.jetbrains.annotations 包,但是如果这有助于解决问题,我也可以切换到另一个实现。

问题是注释变量的无效性检查是在另一种方法中完成的。代码检查器无法识别。

@Nullable
private Bar myVar;

public boolean isNotNull() {
    // This check is actually more complex, but will
    // only ever return true if myVar is not null
    return myVar != null;
}

public void foo() {
    if (isNotNull()) {
        // Here I get a warning that myVar might be null
        myVar.bar();
    }
}

我能否以某种方式让 IntelliJ 识别这种情况?

我怀疑 intellij 在抱怨,因为它不知道 isNotNull() 的 return 值表示 myVar.

的无效性

但是,在您调用 bar().

时它可能为空

一些其他线程可能潜入并在调用 isNotNull() 和使用 myVar 之间将 myVar 改回 null。

保证它的唯一方法是:

  1. 复制myVar到局部变量;
  2. 使用localMyVar != nulllocalMyVar.bar()

如果您的程序是单线程,您不必重写程序来满足 IntelliJ 的检查。 可以验证您的代码的替代工具是 Nullness Checker。 你can run it within IntelliJ.

这是一个MWE。 @EnsuresNonNullIf 注释表示您的规范 "This check ... will only ever return true if myVar is not null."

import org.jetbrains.annotations.Nullable;
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;

public class SO57496219 {

  private @Nullable Object myVar;

  @EnsuresNonNullIf(result = true, expression = "myVar")
  public boolean isNotNull() {
    return myVar != null;
  }

  public void foo() {
    if (isNotNull()) {
      myVar.toString();
    }
  }
}

如果您的程序是多线程,您有多种方法。这里有两个。

  • 如果该字段从未被任何线程重置为 null,您可以将该字段注释为 @MonotonicNonNull。 Nullness Checker 将验证这一事实,而不仅仅是相信它。

  • 可以通过-AconcurrentSemantics命令行选项。这将仅在您更改程序时进行验证,例如将值放入局部变量(如 Andy Turner 所建议的)。但是,如果您希望其他线程同时更改该值,您的程序可能应该使用 locks