我在一个开发人员使用不同 IDE(Eclipse、Netbeans 和 IntelliJ)的环境中工作。我使用@Nonnull 注释 (javax.annotation.Nonnull) 来指示方法永远不会返回 null:
@Nonnull
public List<Bar> getBars() {
return bars; // this.bars is a final, initialized list
}
如果其他开发人员执行以下操作之一,我希望他们收到警告:
- 更改方法以返回 null 而不删除 @Nonnull 注释
- 不必要地检查使用 @Nonnull 显式定义的方法是否为 null: if (foo.getBars() == null) { ... do something ... }
例如,IntelliJ 支持第一种情况。第二个不是;没有警告客户检查 null 是不必要的。
在任何情况下,我们都计划转向返回集合的克隆而不是集合本身,所以最好忘记@Nonnull 并这样做:
public List<Bar> getBars() {
return new ArrayList<Bar>(bars);
}
编辑:
澄清一下,我不考虑为此更改 IDE。我想知道上述 IDE 是否支持我上面描述的内容 - 或者,如果有充分的理由说明为什么不支持它。
我明白不要过分依赖合同。但是,如果我使用最后一段中的样式编写 getBars()(返回列表的克隆),那么例如 IntelliJ 会为任何执行此操作的代码标记警告
if (foo.getBars() == null) { ... }
如果您选择遵循此警告并删除空检查,您似乎同样依赖于 getBars() 实现不会改变。但是,在这种情况下,您似乎依赖于实现细节而不是明确的合同(就像@Nonnull 的情况一样)。
编辑#2:
我不关心执行速度,空检查确实非常快。我担心代码的可读性。考虑以下:
选项 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 更具可读性。由于代码的阅读频率高于编写频率,因此我想确保我(以及我们团队中的其他人)编写的所有代码都尽可能具有可读性。