如何正确使用FindBugs的@CheckForNull、@Nonnull和@Nullable注解
How to use FindBugs’ @CheckForNull, @Nonnull and @Nullable annotations correctly
我想正式注释我的函数签名以阐明它们的契约——特别是如果允许或禁止 null
参数和 return 值——以 FindBugs 的静态代码分析工具 (也许其他)可以利用它。
有两个包(annotations.jar
和 jsr305.jar
),每个包有四个注释来实现此目的,以及根本不放置注释的选项。
这些是我经过一番尝试后的发现:
方法参数:
- 参数不能是
null
:不要放置任何注释。 在这种情况下,如果将 null
传递给方法,则会出现错误标记。 (我在放置 @Nonnull
注释时预料到了这种行为,但是当我放置它时,根本没有错误标记出现。)
- 参数可以是
null
: 放@Nullable
注解。([=15=效果相同]。@Nullable
documentation 读取:“FindBugs 会将带注释的项目视为没有注释。”这是不正确的。如果我调用 string.length()
并且 String string
已被标记为 @Nullable
,它会导致出现错误标记,如果没有注释则不显示错误标记。)
方法return值:
- Method never returns
null
: Put @Nonnull
. 如果你尝试 return null;
从在方法内部。
- 方法可以return
null
:要强制检查吗?如果 return 值确实仅取决于调用时已知的方法参数,则检查可能是一项开销,例如“如果参数一为负,则我的方法 returns null
” .在那种情况下我不会添加注释。但是,您可能需要考虑抛出一个 IllegalArgumentException
而不是 returning null
.
- 方法可以 return
null
并且应该始终检查 return 对象:将 @CheckForNull
. 但是,在许多情况下有更好的方法,您可能需要考虑 returning Collections.emptyList()
而不是 null
列表,或者抛出 MissingResourceException
、IOException
或其他合适的异常。
使用哪个 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 的部分包含更多比较。
我想正式注释我的函数签名以阐明它们的契约——特别是如果允许或禁止 null
参数和 return 值——以 FindBugs 的静态代码分析工具 (也许其他)可以利用它。
有两个包(annotations.jar
和 jsr305.jar
),每个包有四个注释来实现此目的,以及根本不放置注释的选项。
这些是我经过一番尝试后的发现:
方法参数:
- 参数不能是
null
:不要放置任何注释。 在这种情况下,如果将null
传递给方法,则会出现错误标记。 (我在放置@Nonnull
注释时预料到了这种行为,但是当我放置它时,根本没有错误标记出现。) - 参数可以是
null
: 放@Nullable
注解。([=15=效果相同]。@Nullable
documentation 读取:“FindBugs 会将带注释的项目视为没有注释。”这是不正确的。如果我调用string.length()
并且String string
已被标记为@Nullable
,它会导致出现错误标记,如果没有注释则不显示错误标记。)
方法return值:
- Method never returns
null
: Put@Nonnull
. 如果你尝试return null;
从在方法内部。 - 方法可以return
null
:要强制检查吗?如果 return 值确实仅取决于调用时已知的方法参数,则检查可能是一项开销,例如“如果参数一为负,则我的方法 returnsnull
” .在那种情况下我不会添加注释。但是,您可能需要考虑抛出一个IllegalArgumentException
而不是 returningnull
. - 方法可以 return
null
并且应该始终检查 return 对象:将@CheckForNull
. 但是,在许多情况下有更好的方法,您可能需要考虑 returningCollections.emptyList()
而不是null
列表,或者抛出MissingResourceException
、IOException
或其他合适的异常。
使用哪个 JAR 文件:
- 两个 jar 文件都会导致相同的 FindBugs 行为,唯一的区别是来自
annotations.jar
的注释在 Eclipse 中显示为已弃用。所以使用jsr305.jar
. - 需要jar文件。使用给定包和 class 名称创建空注释不起作用。你可以 get it here.
@Paramaeleon 给出了一些很棒的提示,例如您必须如何保留未注释的方法参数,因为如果您编写 @Nonnull
.
如果您愿意尝试不同的静态分析工具,您可以考虑 Nullness Checker of the Checker Framework。
主要区别在于 Nullness Checker 旨在检测所有空指针错误。相比之下,FindBugs 有意不向您报告一些可能的错误,以便报告更少的误报警告。您编写的注释越多,这两种工具都能提供更好的结果。如果您不愿意编写任何注释,那么 FindBugs 是一个更合适的工具。如果你愿意写注解,那么Checker Framework可能会更好
Nullness Checker 手册在其有关 choosing a nullness analysis tool 的部分包含更多比较。