2012-01-06 23 views
15

Następujące nie zawsze zachowują się jak można oczekiwać:Sprawdzanie czy wartość BigDecimal jest zero w wyrażeniu JSP EL

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

Jeśli someBigDecimal ma wartość 0, ale ma skalę inną niż 0, == operacja zwraca wartość false. Oznacza to, że zwraca on wartość true, gdy someBigDecimal jest nowym BigDecimal ("0"), ale wartość false, gdy someBigDecimal jest nowym BigDecimal ("0.00").

Wynika to z JSP, 2.0, 2.1 i 2.2 parametrów, które stanowią:

Na <,> < => =:

Jeżeli A lub B jest BigDecimal, zmusić zarówno A i B do BigDecimal i używają wartości zwracanej przez A.compareTo (B).

Na ==, =:

Jeżeli A lub B jest BigDecimal, zmusić zarówno A i B, a następnie do BigDecimal:

  • Jeżeli operator ==, w obie strony .equals (B)
  • Jeżeli operator! = powrócić! a.equals (B)

Oznacza to, że operatory == ipowodują wywołanie metody .equals(), która porównuje nie tylko wartości, ale także skalę BigDecimals. Inne operatory porównania powodują wywołanie metody .compareTo(), która porównuje tylko te wartości.

Oczywiście dodaje będzie działać:

<c:if test="${not ((someBigDecimal < 0) or (someBigDecimal > 0))}"> 

Ale to raczej brzydki, czy istnieje lepszy sposób to zrobić?

+3

Jakie jest Twoje pytanie? – kcdragon

+0

@ user617090 Zastanawiasz się, jaki jest najlepszy sposób, aby sobie z tym poradzić. Zmieniłem to pytanie, aby było jaśniejsze. –

+0

Co się stanie, jeśli użyjesz '== 0.0'? –

Odpowiedz

10

W JSP 2.2 EL, a powyżej tej wypowiedzi oceni do true:

${someBigDecimal.unscaledValue() == 0} 

Pozwoli to uniknąć utraty precyzji, ale zakłada, że ​​someBigDecimal jest zawsze typu BigDecimal.

custom EL function jest prawdopodobnie najlepszym rozwiązaniem dla starszych wersji EL:

${fn:isZero(someBigDecimal)} 

Istotą problemu jest to, że kod Java ocenia się false ponieważ ZERO ma scale z 0 a nowy BigDecimal ma niezerową skalę:

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

Dzięki za odpowiedź. Na razie utknęliśmy z JSP 2.1. Myśleliśmy o funkcji niestandardowej, ale miałem nadzieję, że tego uniknę. Zgadzam się jednak, że jest to najlepsze podejście. –

2

Dzięki najnowszej wersji EL (obsługiwane przez Tomcat 7 na przykład), można spróbować:

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

Myślę, że byłby to sposób, aby przejść, jeśli byliśmy w specyfikacji JSP 2.2. Moje pytanie ograniczało się do porównywania BigDecimal z literalnym zerem, ale działałoby to również na porównanie dwóch wartości BigDecimal. –

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

Czy mówisz, że 'eq' zachowuje się inaczej niż' == '? Ponieważ rozumiem, że 'eq' jest po prostu aliasem dla' == '. –

+0

Tak, są różne. Podobnie jak relacja między "równym()" i "==" w języku Java. – peakmuma

+1

Przepraszam, ale 'eq' jest po prostu aliasem dla' == '; [nie są różne] (http://stackoverflow.com/questions/2087721/difference-between-eq-and-in-jsp). –

0

Można spróbować signum funkcję:

<c:if test="#{someBigDecimal.signum() == 0}"> 
Powiązane problemy