如何正确使用FindBugs的@CheckForNull、@Nonnull和@Nullable注解

How to use FindBugs’ @CheckForNull, @Nonnull and @Nullable annotations correctly

我想正式注释我的函数签名以阐明它们的契约——特别是如果允许或禁止 null 参数和 return 值——以 FindBugs 的静态代码分析工具 (也许其他)可以利用它。

有两个包(annotations.jarjsr305.jar),每个包有四个注释来实现此目的,以及根本不放置注释的选项。

这些是我经过一番尝试后的发现:

方法参数:

  • 参数不能是 null:不要放置任何注释。 在这种情况下,如果将 null 传递给方法,则会出现错误标记。 (我在放置 @Nonnull 注释时预料到了这种行为,但是当我放置它时,根本没有错误标记出现。)
  • 参数可以是null: 放@Nullable注解。([=15=效果相同]。@Nullabledocumentation 读取:“FindBugs 会将带注释的项目视为没有注释。”这是不正确的。如果我调用 string.length() 并且 String string 已被标记为 @Nullable,它会导致出现错误标记,如果没有注释则不显示错误标记。)

方法return值:

  • Method never returns null: Put @Nonnull. 如果你尝试 return null; 从在方法内部。
  • 方法可以returnnull:要强制检查吗?如果 return 值确实仅取决于调用时已知的方法参数,则检查可能是一项开销,例如“如果参数一为负,则我的方法 returns null” .在那种情况下我不会添加注释。但是,您可能需要考虑抛出一个 IllegalArgumentException 而不是 returning null.
  • 方法可以 return null 并且应该始终检查 return 对象:将 @CheckForNull. 但是,在许多情况下有更好的方法,您可能需要考虑 returning Collections.emptyList() 而不是 null 列表,或者抛出 MissingResourceExceptionIOException 或其他合适的异常。

使用哪个 JAR 文件:

  • 两个 jar 文件都会导致相同的 FindBugs 行为,唯一的区别是来自 annotations.jar 的注释在 Eclipse 中显示为已弃用。所以使用 jsr305.jar.
  • 需要jar文件。使用给定包和 class 名称创建空注释不起作用。你可以 get it here.

@Paramaeleon 给出了一些很棒的提示,例如您必须如何保留未注释的方法参数,因为如果您编写 @Nonnull.

,FindBugs 会不直观地抑制所有警告

如果您愿意尝试不同的静态分析工具,您可以考虑 Nullness Checker of the Checker Framework

主要区别在于 Nullness Checker 旨在检测所有空指针错误。相比之下,FindBugs 有意不向您报告一些可能的错误,以便报告更少的误报警告。您编写的注释越多,这两种工具都能提供更好的结果。如果您不愿意编写任何注释,那么 FindBugs 是一个更合适的工具。如果你愿意写注解,那么Checker Framework可能会更好

Nullness Checker 手册在其有关 choosing a nullness analysis tool 的部分包含更多比较。