当前位置: 首页 > 知识库问答 >
问题:

为什么findbugs在此代码中抛出空指针取消引用?

仲孙鸿飞
2023-03-14

我正在通过Sonarqube在代码上运行findbugs,我得到一个空指针解引用错误:

有一个语句分支,如果执行,保证空值将被取消引用。

故障代码很简单:

public static boolean isBigDecimalDifferent(BigDecimal x, BigDecimal y) {
        return (x != null || y != null)
                && ((x != null && y == null) || (x == null && y != null) || x.compareTo(y) != 0);   
}

我想知道这怎么可能。NPE唯一可能的地方是调用x.compareTo(y)时,但如果x=null,Java将永远不会分析该分支,对吗?

这是一个bug,还是我遗漏了Java分析这条语句的方法?

更新

谢谢你的意见。最后我建议他们改成:

if (x!=null && y != null)
    return x.compare(y);
else
    return x!=y;

我发现这一点更清楚了。如果没有人同意改变,我会按照建议去做,忽略这个问题,尽管我宁愿避免这样。

共有2个答案

何琨
2023-03-14

我会这样写那个方法:

public static boolean isBigDecimalDifferent(BigDecimal x, BigDecimal y) {
   if (x == null) throw new IllegalArgumentException("x cannot be null");
   if (y == null) throw new IllegalArgumentException("y cannot be null");
   return (x.compareTo(y) != 0);
}

我认为它更容易阅读。

如果您不希望在异常中表达先决条件,我会说这也更清楚:

public static boolean isBigDecimalDifferent(BigDecimal x, BigDecimal y) {
   if (x == null) return (y != null);
   if (y == null) return (x != null);
   return (x.compareTo(y) != 0);
}
萧丁雨
2023-03-14

对于FindBugs来说,逻辑太复杂了,这里的逻辑是错误的。您是对的,您在该代码中对取消引用null进行了辩护。

我会简化它,这样FindBugs就可以理解它,这样任何后续的人类读者也可以很容易地弄清楚它在做什么:

public static boolean isBigDecimalDifferent(BigDecimal x, BigDecimal y) {
    if (x == null) {
        return y != null;
    }
    if (y == null) {
        return x != null;
    }
    return x.compareTo(y) != 0;
}

旁注:通常,您会有一个方法来检查是否相等,并使用 如果要检查不平等。

您在评论中说:

不幸的是,这是我无权更改的遗留代码(我真希望我可以!)

然后您必须注意FindBugs无法解决它,并将其作为FindBugs设置中的异常(在本问题的答案中描述)。

 类似资料:
  • 嗨我有以下方法: 不得不提的是,startDate和endDate是长变量。我尝试在if条件中添加null检查,也尝试使用longValue()方法,但没有结果。你知道我怎样才能解决这个问题吗?可能是fndBugs端的bug?

  • 我正在代码中运行findBugs测试。 它报告NP_NULL_ON_SOME_PATH:以下代码中可能存在空指针解引用。 我不明白为什么它会这样报告?

  • 我已经在我的sonar实例上测试了规则“正确性--可能的空指针取消引用”和“正确性--在异常路径的方法中可能的空指针取消引用”。不幸的是,以下代码从未被检测为错误 Netbeans能够正确检测到此问题,但sonar 3.6.1不能。 谢谢你的帮助

  • 问题内容: 我正在android中做一个应用程序,因此我需要访问com.android.internal.telephony API。现在,我可以访问这些API了,但问题是,无论我在自己的类中调用Class Call.java方法的什么地方,都会抛出。您可以在http://hi- android.info/src/com/android/internal/telephony/Call.java.h

  • 风格: 日志消息:10-10 13:20:01.184:E/AndroidRuntime(1417):致命异常:main 10-10 13:20:01.184:E/AndroidRuntime(1417):android。看法WindowManager$BadTokenException:无法添加窗口--android令牌。应用程序。本地活动管理器$LocalActivityRecord@411e