在JSP EL表达式中测试BigDecimal值是否为零

19

以下代码的行为并不总是如你所预期:

<c:if test="${someBigDecimal == 0}">
如果一个BigDecimal的值为0,但小数位数不为0,则“==”操作会返回false。也就是说,当someBigDecimal是new BigDecimal("0")时,它将返回true,但当someBigDecimal是new BigDecimal("0.00")时,它将返回false。
这是由JSP 2.0、2.1和2.2规范引起的,其中规定:
对于<、>、<=、>=:
如果A或B是BigDecimal,则将A和B强制转换为BigDecimal,并使用A.compareTo(B)的返回值。
对于==、!=:
如果A或B是BigDecimal,则将A和B强制转换为BigDecimal,然后:
- 如果运算符是==,则返回A.equals(B)。 - 如果运算符是!=,则返回!A.equals(B)。
这意味着“==”和“!=”操作符会调用“equals()”方法,该方法比较BigDecimal的值和小数位数。其他比较运算符会调用“compareTo()”方法,该方法仅比较值。
当然,以下代码也可以工作:
<c:if test="${not ((someBigDecimal < 0) or (someBigDecimal > 0))}">

但这样做相当丑陋,有没有更好的方法?


如果你使用 == 0.0 会发生什么? - Dave Newton
@Dave Newton - 我尝试了一下Tomcat 6的测试,字面上的0.0被强制转换为一个BigDecimal,其值为0,比例为0,所以没有任何区别。即使它有一个比例为1,JSP规范只说该值应该被强制转换为BigDecimal,但没有提及比例,因此行为将是不可预测的。 - John S
@Dave Newton - 我可能说错了不可预测的部分。根据JSP 2.2规范的1.18.3节,0.0将被强制转换为一个使用双精度'BigDecimal'构造函数的BigDecimal。这意味着无论小数点后有多少个零,结果的BigDecimal始终具有0的比例。 - John S
5个回答

13

在JSP 2.2 EL及以上版本中,此表达式将被评估为true

${someBigDecimal.unscaledValue() == 0}

这将避免任何精度损失,但假设someBigDecimal始终是BigDecimal类型。

对于较旧版本的EL,自定义EL函数可能是最佳选择。

${fn:isZero(someBigDecimal)}

问题的核心在于,这段 Java 代码的求值结果为 false,因为 ZEROscale0,而新的 BigDecimal 具有非零的 scale 值:

BigDecimal.ZERO.setScale(3).equals(BigDecimal.ZERO)

谢谢你的回答。目前我们还在使用JSP 2.1版本。我们曾考虑过自定义函数,但我希望能够避免这种方式。不过现在我同意这是最好的方法。 - John S

4
<c:if test="${someBigDecimal.compareTo(BigDecimal.ZERO) == 0}">

我认为如果我们使用 JSP 2.2 规范,这将是正确的方法。我的问题仅限于将 BigDecimal 与文字零进行比较,但这也适用于将两个 BigDecimal 值进行比较。 - John S

2
你可以尝试使用符号函数:
<c:if test="#{someBigDecimal.signum() == 0}">

2
<c:if test="${someBigDecimal eq 0}">

1
你是在说 eq== 的行为不同吗?因为我理解 eq 只是 == 的别名。 - John S
是的,它们是不同的。就像Java中'equal()'和'=='之间的关系一样。 - peakmuma
2
抱歉,但 eq 只是 == 的别名;它们没有区别。参考链接 - John S
eq 表示 equals() 方法。这里equals()== 的区别。 - peakmuma
1
你的链接是Java的,但这是JSP EL表达式语言,其中eq==相同。如果你读了问题,你会发现==会导致调用.equals()。事实上,这就是问题的重点。 - John S
抱歉,我对你的问题有误解。在我的开发环境中,使用 ==eq 得到了不同的结果。我不知道原因,可能是我理解错了。我会在下周一检查我的代码。 - peakmuma

2

使用最新版的EL(例如Tomcat 7支持的版本),您可以尝试以下操作:

<c:if test="${someBigDecimal.doubleValue() == 0}">

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接