Тестирование, если значение BigDecimal равно нулю в выражении EL JSP
Следующее не всегда ведет себя так, как вы ожидали:
<c:if test="${someBigDecimal == 0}">
Если someBigDecimal имеет значение 0, но имеет шкалу, отличную от 0, операция == возвращает false. То есть, он возвращает true, когда someBigDecimal является новым BigDecimal ( "0" ), но false, когда someBigDecimal является новым BigDecimal ( "0.00" ).
Это результат спецификаций 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)
- Если оператор равен! =, return! A.equals(B)
Это означает, что операторы ==
и !=
приводят к вызову метода .equals()
, который сравнивает не только значения, но также масштаб BigDecimals. Другие операторы сравнения приводят к вызову метода .compareTo()
, который сравнивает только значения.
Конечно, будет работать следующее:
<c:if test="${not ((someBigDecimal < 0) or (someBigDecimal > 0))}">
Но это довольно уродливо, есть ли лучший способ сделать это?
Ответы
Ответ 1
В JSP 2.2 EL и выше это выражение будет оцениваться до true
:
${someBigDecimal.unscaledValue() == 0}
Это позволит избежать потери точности, но предполагает, что someBigDecimal
всегда имеет тип BigDecimal
.
A пользовательская функция EL, вероятно, лучший подход для более старых версий EL:
${fn:isZero(someBigDecimal)}
Ядро проблемы состоит в том, что этот код Java оценивается как false
, потому что ZERO
имеет scale 0
и новый BigDecimal
имеет ненулевую шкалу:
BigDecimal.ZERO.setScale(3).equals(BigDecimal.ZERO)
Ответ 2
<c:if test="${someBigDecimal.compareTo(BigDecimal.ZERO) == 0}">
Ответ 3
<c:if test="${someBigDecimal eq 0}">
Ответ 4
В последней версии EL (поддерживаемой Tomcat 7, например) вы можете попробовать:
<c:if test="${someBigDecimal.doubleValue() == 0}">
Ответ 5
Вы можете попробовать функцию signum:
<c:if test="#{someBigDecimal.signum() == 0}">