如何修复Findbugs问题“保证Null值被取消引用”NP_GUARANTEED_DEREF

时间:2011-03-16 17:13:37

标签: java nullpointerexception findbugs dereference correctness

您好我有一些代码被Findbugs报告为NP_GUARANTEED_DEREF问题。 现在看我的代码我不太明白它有什么问题,任何人都可以提出问题所在。

public void test() {
  String var = "";
  int index = 2;
  if (index == -1) {
    var = String.class.getName();
    if (var.length() == 0) {
      var = null;
    }
  } else {
    var = Integer.class.getName();
    if (var.length() == 0) {
      var = null;
    }
  }
  if (var == null) {// FINBUGS reports on this line NP_GUARANTEED_DEREF
    /*
     * There is a statement or branch that if executed guarantees that a value
     * is null at this point, and that value that is guaranteed to be
     * dereferenced (except on forward paths involving runtime exceptions).
     */
    throw new NullPointerException("NULL");
  }
}

现在深入研究Findbugs中的错误,它突出显示var = null;的两个赋值作为错误的原因,但我不太明白为什么。这并不像我实际上正在对var对象做任何事情我正在进行空检查。该示例取自实际生产代码,但剥离了重现错误所不需要的任何内容。我想知道这是否是误报。如果没有,那将是一个合适的解决方案。

以下是Findbugs Bug Detail的链接:http://findbugs.sourceforge.net/bugDescriptions.html#NP_GUARANTEED_DEREF

[更新]收到关于此问题的一些反馈后,我现在在Sourceforge上的Findbugs Bugtracker中将其记录为误报,链接为https://sourceforge.net/tracker/?func=detail&aid=3277814&group_id=96405&atid=614693

关于这个问题的谈话将继续进行。

4 个答案:

答案 0 :(得分:5)

我明白了。我可以在我的电脑上确认相同的FB行为。看起来很奇怪。有趣的是,如果你用throw new NullPointerException替换throw new RuntimeException,错误标记就会消失。

现在我想我明白了他们的意思。消息的措辞并不准确,但它们会警告您不要使用NPE。我猜他们认为明确地将NPE作为一种不好的做法。

答案 1 :(得分:3)

这是FindBugs中的一个错误,在他们的问题跟踪器页面上发布此问题。 findbugs.sf.net

答案 2 :(得分:2)

好的,FindBugs正在寻找的是一个声明或分支,它可以保证导致空指针异常。最初,我们只查找空值的解引用。我们后来增加了分析来处理

if (x == null) throw new NullPointerException()

与x的显式解引用相同。这主要是为了帮助进行过程间分析,因此对其参数进行显式空值检查的方法将与在没有显式空值检查的情况下取消引用其参数的方法相同,并在为这些参数传递空值时报告错误。

因此,我们的错误消息中的一些文本可能需要更新,但我们确实没有发现许多会导致混淆的实际情况。

我不太确定上面代码的目的是什么。在为var分配null的位置,您将创建一种情况,该情境将导致显式抛出空指针异常。这真的是你想要的行为吗?

答案 3 :(得分:0)

仔细查看错误消息here的定义,它说:

  

有一个声明或分支if   执行保证值是   此时为null,该值为null   保证被解除引用   (涉及的前进路径除外)   运行时异常)

这让我觉得它只是让你知道var将会为null或者实际上是什么让findbugs认为var在if语句中被引用。

您发布的代码看起来很好,我会仔细检查真实代码中是否未访问var。

我唯一可能改变的就是向后写这样的比较:

if (null == var)

这样很明显,如果你遗漏了=的/ /

之一