JetBrains @Contract 使用字段

JetBrains @Contract using field

我有以下 class*:

public class MyClass {

  @Nullable
  private String mString;

  /* ... */

  public boolean contains(@NotNull final String text) {
    if(!isNullOrEmpty()) {
      return mString.contains(text);
    } else {
      return false;
    }
  }

  public boolean isNullOrEmpty() {
      return mString == null || mString.isEmpty();
  }
}

现在在 mString.contains(text),IntelliJ 警告我 mString 可能是 null,尽管可以保证它不是。我注意到 JetBrains 有 @Contract 注释。有没有一种方法可以注释 isNullOrEmpty(),以便在方法 returns true?

时不会收到此警告

我希望 @Contract 注释将接近 Java Modeling Language 功能,如下所示:

//@ ensure \result == true ==> mString != null;
public boolean isNullOrEmpty() {
  return mString == null || mString.isEmpty();
}

此外,我希望 isNullOrEmpty() 保持无参数,因为它是 public API.

的一部分

*只是一个虚构的class用于演示目的:)实际代码使用更复杂的class.

嗯,因为你用 @Nullable 注释了 mString,所以 mString 很可能是 null。这是工作中的静态分析;您已经声明此字段可能是也可能不是 null,因此 IntelliJ 会通知您。

考虑为什么该字段用 @Nullable 注释。也许应该是 @NotNull?

请记住,我只在 contains 方法中收到警告,因为 IntelliJ 正在做聪明的事情;它知道如果 mString == null,则不会评估另一个条件

提醒一下:@Contract only applies to the arguments。它不会检查与字段有关的任何内容,这就是为什么人们会对字段进行不同的注释(使用 @Nullable@NonNull@MagicConstant 等)。

您的 mString 是可变的,因此在检查“isNullOrEmpty”和访问“mString.contains”之间可以更改 mString 值。所以这就是为什么 @Contract 注解只对方法参数有效的原因。如果您的方法 isNullOrEmpty 如下所示,您可以使用 @Contract

public boolean isNullOrEmpty(String pString) {}

您可以为此使用 @Contract 注释,但您可能必须将 isNull 方法更改为:

@Contract("null -> true; !null -> false")
private boolean isNull(String value) {
  return value == null;
}

然后您应该可以像这样使用其他方法:

  public boolean contains(@NotNull final String text) {
    if(!isNull(text)) {
      return mString.contains(text);
    } else {
      return false;
    }
  }

但是,我不确定这比这个更好:

  public boolean contains(@NotNull final String text) {
    if(text != null) {
      return mString.contains(text);
    } else {
      return false;
    }
  }