javax.annotation.Nonnull vs assert

时间:2013-02-11 10:14:55

标签: java assert findbugs null-check

我在方法参数上使用Findbugs和javax.annotation.Nonnull。

在私有方法上,我通常会添加一个断言行来检查

之类的空值
private void myMethod(@Nonnull String str) {
    assert str != null
    ....

最新的Netbeans版本(7.3rc2)报告不需要断言检查(因为Nonnull注释)。我不完全确定这是一个Netbeans错误。

可以删除断言行,因为我指定了@Nonnull注释吗?

据我所知,注释仅在静态分析期间使用,而assert在启用时在执行期间处于活动状态,因此两者不是替代。

4 个答案:

答案 0 :(得分:12)

在运行时评估断言,该注释有助于FindBugs在运行时分析期间捕获问题。由于两个检查都没有真正冲突,你可以保留它们。如果我的IDE告诉我删除断言,我会觉得很烦人。

答案 1 :(得分:8)

Netbeans是对的。如果您认为它可以为null:删除注释。如果您知道它不能:删除断言。

如果有可能使用空值调用您的方法,则@Nonnull注释不应该存在。

就像你说的那样,该注释实际上并没有在运行时做任何事情:它仅由IDE和静态代码分析工具使用。它不能确保事物不为空。

答案 2 :(得分:1)

由于这是私有方法,我们可以确保带注释的参数不能为null。我想你可以删除这个断言。

如果NetBeans警告公共方法,我认为它有问题。我建议你把断言。

如果您仍然认为私有方法中的断言是必要的,我认为您可以使用字节码注入。 例如,这是一个注入空检查的maven插件。对不起,这是我的个人项目,但对我有用。我想它可以满足你的需求。 https://github.com/KengoTODA/jsr305-maven-plugin

答案 3 :(得分:0)

我找到了一个不同的解决方案,因为我正在思考我的IDE警告。

最初,我觉得IDE错了。我是一个偏执的程序员,并希望获得文档和标签的标签。静态分析 AND 运行时检查,以防我从反射,或其他JVM语言或不可静态分析的东西中使用它,所以我认为给我一个警告并告诉它是错误的我不需要assert(x != null)声明。

但后来我考虑了如何根据在运行时传递给Java的-ea标志的状态来删除断言,并且在某些方面assert@Nonnull实际上都是仅限开发的检查。

事实证明,可以插入一个实际的运行时检查(Java 7+)Objects.requireNonNull,它将抛出NullPointerException并且无法通过-ea断言删除。我想我会更喜欢这个assert(x != null); use(x);模式。

public ConstructorForClass(@Nonnull Type x) {
  this.x = Objects.requireNonNull(x);
  //...
}