为什么 findbugs 在此代码中抛出空指针取消引用?
Why is findbugs throwing a null pointer dereference in this code?
我 运行 通过 Sonarqube 在我们的代码中查找错误,并且我收到空指针取消引用的错误:
There is a branch of statement that, if executed, guarantees that a
null value will be dereferenced.
错误的代码就是这样:
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 将永远不会分析该分支,对吗?
这是一个错误,还是我遗漏了一些有关 Java 分析此语句的方式的信息?
更新
感谢您的投入。我最终建议他们将其更改为:
if (x!=null && y != null)
return x.compare(y);
else
return x!=y;
我觉得更清楚一点。如果没有人同意更改,我将按照建议进行操作并忽略该问题,即使我宁愿避免那样做。
我会这样写那个方法:
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);
}
我认为它更容易阅读。
如果你不想在异常中表达 pre-conditions 我会说这也更清楚:
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 的逻辑太复杂了,这里出错了。你是对的,你在该代码中防御了取消引用 null
。
我会简化它,以便 FindBugs 理解它,这样任何后续的人 reader 也可以轻松地弄清楚它在做什么:
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;
}
旁注:通常,您会有一种方法来检查 相等性 ,如果要检查不等性,请使用 !
。
您在评论中说:
Unfortunately, it is legacy code that I haven't authority to change (I do wish I could!)
那么你必须注意到 FindBugs 无法解决这个问题,并在你的 FindBugs 设置中将其设为例外 (described in this question's answers)。
我 运行 通过 Sonarqube 在我们的代码中查找错误,并且我收到空指针取消引用的错误:
There is a branch of statement that, if executed, guarantees that a null value will be dereferenced.
错误的代码就是这样:
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 将永远不会分析该分支,对吗?
这是一个错误,还是我遗漏了一些有关 Java 分析此语句的方式的信息?
更新
感谢您的投入。我最终建议他们将其更改为:
if (x!=null && y != null)
return x.compare(y);
else
return x!=y;
我觉得更清楚一点。如果没有人同意更改,我将按照建议进行操作并忽略该问题,即使我宁愿避免那样做。
我会这样写那个方法:
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);
}
我认为它更容易阅读。
如果你不想在异常中表达 pre-conditions 我会说这也更清楚:
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 的逻辑太复杂了,这里出错了。你是对的,你在该代码中防御了取消引用 null
。
我会简化它,以便 FindBugs 理解它,这样任何后续的人 reader 也可以轻松地弄清楚它在做什么:
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;
}
旁注:通常,您会有一种方法来检查 相等性 ,如果要检查不等性,请使用 !
。
您在评论中说:
Unfortunately, it is legacy code that I haven't authority to change (I do wish I could!)
那么你必须注意到 FindBugs 无法解决这个问题,并在你的 FindBugs 设置中将其设为例外 (described in this question's answers)。