回答
这是因为 BigDecimal
的 equals()
不仅比较数值的大小,而且还比较数值的精度。这就意味着,即使两个 BigDecimal
对象代表相同的数值,但如果它们的精度不同,equals()
方法会认为这两个对象不相等。
详解
@Test
public void test01() {
BigDecimal bd1 = new BigDecimal("2.00");
BigDecimal bd2 = new BigDecimal("2.0");
System.out.println(bd1.equals(bd2));
}
// 执行结果...
false
两个值数值一样,但是得到的结果却是 false。我们看 equals()
的源码:
在源码中我们发现,它会比较两个数值的精度。这两个值的精度是不一样的:
在大多数情况下,特别是在处理金融数值时,我们其实只关心数值是否相等,而不关心它们的精度是否完全一样。在这种情况下,我们应该使用 compareTo()
而不是 equals()
,因为 compareTo()
会忽略数值的精度,只比较它们的大小。
public int compareTo(BigDecimal val) {
// Quick path for equal scale and non-inflated case.
if (scale == val.scale) {
long xs = intCompact;
long ys = val.intCompact;
if (xs != INFLATED && ys != INFLATED)
return xs != ys ? ((xs > ys) ? 1 : -1) : 0;
}
int xsign = this.signum();
int ysign = val.signum();
if (xsign != ysign)
return (xsign > ysign) ? 1 : -1;
if (xsign == 0)
return 0;
int cmp = compareMagnitude(val);
return (xsign > 0) ? cmp : -cmp;
}
- 如果返回值等于
0
,则表示两个BigDecimal
对象数值上相等。 - 如果返回值大于
0
,则表示调用对象数值大于参数对象。 - 如果返回值小于
0
,则表示调用对象数值小于参数对象。
同时,阿里巴巴的 Java 开发手册也是不允许使用 equals()
来比较两个 BigDecimal 数值是否相等。