带有不同IDE的@Nonnull - 警告不必要的空检查

Lau*_*rpf 5 java findbugs intellij-idea jsr305

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

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

如果他们执行以下操作之一,我希望其他开发人员收到警告:

  1. 将方法更改为返回null而不删除@Nonnull注释
  2. 对于使用@Nonnull明确定义的方法,不必要地检查null:if(foo.getBars()== null){...做某事......}

IntelliJ支持第一种方案.第二个不是; 客户端不会被警告不需要检查null.

我们无论如何都计划转向收集集合的克隆而不是集合本身,所以最好忘记@Nonnull而是这样做:

public List<Bar> getBars() {
  return new ArrayList<Bar>(bars);
}
Run Code Online (Sandbox Code Playgroud)

编辑:

为了澄清,我不打算为此更改IDE.我想知道上面提到的IDE是否支持我上面描述的内容 - 或者,如果有充分理由说明为什么它不受支持.

我明白了不要太依赖合同.但是,如果我用最后一段中的样式编写getBars()(返回列表的克隆),那么例如IntelliJ会标记任何代码的警告

if (foo.getBars() == null) { ... }
Run Code Online (Sandbox Code Playgroud)

如果您选择遵循此警告并删除空检查,则您似乎同样依赖于不更改的getBars()实现.但是,在这种情况下,您似乎依赖于实现细节而不是显式合同(与@Nonnull的情况一样).

编辑#2:

我不关心执行速度,空检查确实非常快.我担心代码可读性.考虑以下:

选项A:

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

选项B:

if (foo.getBars().size() < MAXIMUM_BARS && 
    baz.getFoos().size() < MAXIMUM_FOOS) {
  // do something
}
Run Code Online (Sandbox Code Playgroud)

我认为选项B比选项A更具可读性.由于代码的读取频率高于编写代码,因此我希望确保所有代码I(以及我们团队中的其他代码)编写尽可能可读.

bar*_*uin 6

我会推荐以下内容:

  • 坚持你@Nonnull@Nullable注释,就像你已经这样做.
  • 定义并实施默认值.默认值是什么并不重要,但在整个代码库中它应该是相同的.
  • 使用FindBugs检查你的案例1和2. FindBugs有大多数IDE的插件,我看到了Eclipse,Netbeans和IntelliJ,但还有更多.(RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE规则涵盖了2号案例.我对它进行了测试.我认为在阅读本页其他地方的DavidHarkness评论之后我应该提一下.)

这种方法与IDE无关,也适用于像Hudson或Jenkins这样的外部构建环境.