检查用@Nonnull注释的参数是否为null?


19

我们已经开始使用FindBugs并@Nonnull适当地注释了我们的参数,它很有效地指出了周期早期的错误。到目前为止,我们一直在null使用Guava的方法继续检查这些参数checkNotNull,但我宁愿null仅在边缘进行检查-无需检查即可输入值的地方null,例如SOAP请求。

// service layer accessible from outside
public Person createPerson(@CheckForNull String name) {
    return new Person(Preconditions.checkNotNull(name));
}

...

// internal constructor accessed only by the service layer
public Person(@Nonnull String name) {
    this.name = Preconditions.checkNotNull(name);  // remove this check?
}

我了解这本身@Nonnull并不会阻止null价值观。

但是,鉴于FindBugs会指出将值从未标记字段转移到已标记字段的任何地方@Nonnull,我们是否可以依靠它来捕获这些情况(它确实如此),而不必在null传递给它们的任何地方检查这些值系统?我是否天真地想要信任该工具并避免进行这些冗长的检查?

底线:虽然删除null下面的第二张支票似乎很安全,但这是不好的做法吗?

这个问题可能与“ 如果有人不希望null是否应该检查null”这个问题太相似了,但是我要特别问一下@Nonnull注解。

Answers:


6

如果您不信任FindBug,则可以选择使用断言。这样,您可以避免用户MSalters提到的问题,但仍然可以进行检查。当然,如果这种快速失败的方法不可行,则该方法可能不适用,即您必须捕获任何异常。

并进一步回答这个问题是否不好。好吧,这是有争议的,但我认为不是。我认为此FindBug注释是遵循合同设计原则的轻量级规范。

在按合同设计时,您需要在方法及其调用者之间建立合同。合同包括调用方在调用该方法时同意满足的前提条件,以及一个前提条件,如果满足其前提条件,则该条件在执行后又由该方法满足。

这种开发方法的好处之一是,您可以避免所谓的防御性编程风格(在其中显式检查所有无效参数值等)。相反,您可以依靠合同,避免重复检查以提高性能和可读性。

合同可用于运行时声明检查,该检查遵循上述“故障优先”原则,在这种原则中,您希望程序在合同违约时失败,从而为您提供识别错误源的线索。(失败的前提条件意味着调用者做错了什么,失败的前提条件表明给定方法的实现错误)

此外,合同可用于静态分析,它试图在不实际运行源代码的情况下得出有关源代码的结论。

@nonnull批注可以看作是工具FindBugs用于静态分析的前提。如果您喜欢诸如运行时断言检查之类的方法,即故障优先策略,则应考虑将断言语句用作内置Java。或者也许使用行为接口规范语言(例如Java Modeling Language(JML))来适应更复杂的规范策略。

JML是Java的扩展,其中规范嵌入在特殊的Java注释中。这种方法的优点是,即使使用仅依赖规范而不是实现细节的开发方法,也可以使用复杂的规范,并且可以使用各种使用该规范的工具,例如上述的运行时断言检查工具,自动生成单元测试或文档。

如果您同意@nonnull是(轻型)合同的观点,则通常不添加其他检查的做法是常规做法,因为此原理背后的初衷是避免防御性编程。


2
这正是我使用@Nonnull:作为合同规范的方式。我一直在取消合同背后的防御性检查,到目前为止没有任何麻烦。
David Harkness,2012年

4

好吧,考虑一下为什么你不写

this.name = Preconditions.checkNotNull(name);  // Might be necessary
that.name = Preconditions.checkNotNull(this.name);  // Who knows?

编程不是黑魔法。变量不会突然变为Null。如果你知道一个变量是不是空的,你知道它没有发生变化,那么就不会检查。

如果您进行检查,将来的某些程序员(可能是您)将花费大量时间来找出执行该检查的原因。毕竟,支票一定是有原因的,那么您忽略了什么?


3
@Nonnull合同规定,调用者不得传递null给构造函数,和FindBugs的使用静态分析,以找到可能允许呼叫null--specifically是将值没有标明调用@Nonnull自己。但是,呼叫者可以随意传递null并忽略FindBugs发出的警告。
David Harkness 2012年

理想情况下,编程不是黑魔法。不幸的是,警告和惊喜比比皆是,尤其是在使用其中的一些并发代码时
Tim Harper
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.