java - @Nonnull 与不同的 IDE - 警告不必要的空检查

标签 java intellij-idea findbugs jsr305

我在一个开发人员使用不同 IDE(Eclipse、Netbeans 和 IntelliJ)的环境中工作。我正在使用 @Nonnull 注释 (javax.annotation.Nonnull) 来指示方法永远不会返回 null:

@Nonnull
public List<Bar> getBars() {
  return bars;  // this.bars is a final, initialized list
}

我希望其他开发人员在执行以下操作时收到警告:

  1. 在不移除@Nonnull 注释的情况下更改返回 null 的方法
  2. 不必要地检查用@Nonnull 显式定义的方法是否为 null:if (foo.getBars() == null) { ... do something ... }

支持第一种情况,例如通过 IntelliJ。第二个不是;不会警告客户端检查 null 是不必要的。

在任何情况下,我们都计划转向返回集合的克隆而不是集合本身,所以最好忘记 @Nonnull 并改为执行此操作:

public List<Bar> getBars() {
  return new ArrayList<Bar>(bars);
}

编辑:

澄清一下,我没有考虑为此更改 IDE。我想知道上述 IDE 是否支持我上面描述的内容 - 或者,是否有充分的理由说明为什么不支持它。

我明白了不要过分依赖契约(Contract)的意思。但是,如果我用最后一段中的样式编写 getBars() (返回列表的克隆),那么例如IntelliJ 会为任何执行此操作的代码标记警告

if (foo.getBars() == null) { ... }

如果您选择遵循此警告并删除 null 检查,您似乎同样依赖于 getBars() 实现不变。但是,在这种情况下,您似乎依赖于实现细节而不是显式契约(Contract)(@Nonnull 就是这种情况)。

编辑#2:

我不关心执行速度,null 检查确实非常快。我担心代码的可读性。考虑以下几点:

选项 A:

if ((foo.getBars() == null || foo.getBars().size() < MAXIMUM_BARS) && 
    (baz.getFoos() == null || baz.getFoos().size() < MAXIMUM_FOOS)) { 
  // do something
}

选项 B:

if (foo.getBars().size() < MAXIMUM_BARS && 
    baz.getFoos().size() < MAXIMUM_FOOS) {
  // do something
}

我认为选项 B 比选项 A 更具可读性。由于阅读代码的次数多于编写代码的次数,因此我想确保我(以及我们团队中的其他人)编写的所有代码都尽可能具有可读性。

最佳答案

我会推荐以下内容:

  • 坚持使用您的 @Nonnull@Nullable 注释,就像您已经在做的那样。
  • 定义并执行默认值。默认值是什么并不重要,但整个代码库中的默认值应该相同。
  • 使用FindBugs检查您的案例 1 和 2。FindBugs 有适用于大多数 IDE 的插件,我看到提到了 Eclipse、Netbeans 和 IntelliJ,但还有更多。 (第 2 种情况包含在 RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE 规则中。我测试了它。我只是想在阅读本页其他地方的 DavidHarkness 评论后提及这一点。)

这种方法与 IDE 无关,也适用于 Hudson 或 Jenkins 等外部构建环境。

关于java - @Nonnull 与不同的 IDE - 警告不必要的空检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21375867/

相关文章:

scala - 在 IntelliJ 中链接到外部 Scala API 文档

java - 通过 findbugs 对象使用 Findbugs 测试类

java - 如何知道哪个 JSP 网页正在显示我的 servlet

java - 正则表达式获取字符串中两个单词之间的值

java - Bazel - 无法使用 Android Studio 构建

java - 如何在java中将源代码附加为依赖项

findbugs - 在增量构建中检查样式、PMD、FindBugs

ant - CreateProcess error=206,文件名或扩展名太长

java 代理 - 检测选定的文件(排除所有内置的 java 类和方法)

java - Keycloak 身份代理 API