【问题标题】:javax.annotation.Nonnull vs assertjavax.annotation.Nonnull 与断言
【发布时间】:2013-01-26 10:19:21
【问题描述】:

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

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

private void myMethod(@Nonnull String str) {
    assert str != null
    ....

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

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

据我了解,注释仅在静态分析期间使用,而断言在启用时在执行期间处于活动状态,因此两者不可替代。

【问题讨论】:

  • 在 Programmers.SE 上查看 related question
  • lombok.NonNull 为您添加代码。

标签: java assert findbugs null-check


【解决方案1】:

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

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

正如您所说,该注解在运行时实际上并没有做任何事情:它仅由 IDE 和静态代码分析工具使用。它不能确保事物不为空。

【讨论】:

  • 在示例中,我假设参数永远不应为空。
  • 通过添加我告诉 Findbugs 的注释“带注释的元素不能为空”。 Findbugs 将检查对该方法的所有调用,以确保参数永远不会为空。所以需要注释(在这种情况下)。问题是“断言有用吗?”。 Findbugs 在分析中可能是错误的,因此断言可以涵盖 Findbugs 未检测到的动态情况
  • 实际上,开发人员想要两者兼得。当发生代码分析未涵盖的事情时,断言将使其快速失败。注释将突出显示开发过程中的错误。因此,尽管您的回答在理论上是正确的,但我不建议您删除任何内容。
  • FindBugs 确实不是万无一失的,它会努力发现问题,但并不总是有效。断言是您的运行时安全网。
【解决方案2】:

由于这是私有方法,我们可以确保带注释的参数不能为空。我认为您可以删除此断言。

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

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

【讨论】:

    【解决方案3】:

    assert 在运行时被评估,注解帮助 FindBugs 在运行前的分析过程中发现问题。由于这两项检查并不真正冲突,您可以同时保留它们。如果我的 IDE 告诉我删除断言,我会觉得很烦人。

    【讨论】:

    • 不仅 FindBugs,而且现代 IDE(如 IntelliJ)也在其分析中使用它。
    • 是的 IDE 正在迎头赶上,但我也喜欢在构建期间(在 IDE 之外)运行它,并在构建过程中失败以防发现严重问题。
    【解决方案4】:

    我找到了一个不同的解决方案,因为我正在考虑我的 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);
      //...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-13
      • 1970-01-01
      • 2016-06-21
      • 2010-09-29
      • 1970-01-01
      • 1970-01-01
      • 2010-11-26
      相关资源
      最近更新 更多