TL; DR
Verwenden Sie eine davon für universelle Konvertierungsanforderungen
//Java 7 or below
bigDecimal.setScale(0, RoundingMode.DOWN).intValueExact()
//Java 8
bigDecimal.toBigInteger().intValueExact()
Argumentation
Die Antwort hängt davon ab, welche Anforderungen gestellt werden und wie Sie diese Frage beantworten.
- Wird der
BigDecimal
potenziell einen Bruchteil ungleich Null haben?
- Passt das
BigDecimal
möglicherweise nicht in den Integer
Bereich?
- Möchten Sie Bruchteile ungleich Null gerundet oder abgeschnitten?
- Wie möchten Sie, dass Bruchteile ungleich Null gerundet werden?
Wenn Sie die ersten beiden Fragen mit Nein beantwortet haben, können Sie sie einfach BigDecimal.intValueExact()
wie von anderen vorgeschlagen verwenden und in die Luft jagen lassen, wenn etwas Unerwartetes passiert.
Wenn Sie in Bezug auf Frage 2 nicht absolut 100% sicher sind, intValue()
ist dies immer die falsche Antwort.
Es besser machen
Verwenden wir die folgenden Annahmen basierend auf den anderen Antworten.
- Wir sind damit einverstanden, an Präzision zu verlieren und den Wert abzuschneiden, denn genau das
intValueExact()
tun Auto-Boxing
- Wir möchten, dass eine Ausnahme ausgelöst wird, wenn der
BigDecimal
Wert größer als der Integer
Bereich ist, da alles andere verrückt wäre, es sei denn, Sie haben einen ganz bestimmten Bedarf an dem Umlauf, der auftritt, wenn Sie die höherwertigen Bits ablegen.
Wenn diese Parameter gegeben sind, wird intValueExact()
eine Ausnahme ausgelöst, wenn dies nicht gewünscht wird, wenn unser Bruchteil nicht Null ist. Auf der anderen Seite intValue()
wirft keine Ausnahme, wenn es sollte, wenn unsere BigDecimal
zu groß ist.
Um das Beste aus beiden Welten zu erhalten, runden Sie die BigDecimal
erste ab und konvertieren Sie dann. Dies hat auch den Vorteil, dass Sie mehr Kontrolle über den Rundungsprozess haben.
Spock Groovy Test
void 'test BigDecimal rounding'() {
given:
BigDecimal decimal = new BigDecimal(Integer.MAX_VALUE - 1.99)
BigDecimal hugeDecimal = new BigDecimal(Integer.MAX_VALUE + 1.99)
BigDecimal reallyHuge = new BigDecimal("10000000000000000000000000000000000000000000000")
String decimalAsBigIntString = decimal.toBigInteger().toString()
String hugeDecimalAsBigIntString = hugeDecimal.toBigInteger().toString()
String reallyHugeAsBigIntString = reallyHuge.toBigInteger().toString()
expect: 'decimals that can be truncated within Integer range to do so without exception'
//GOOD: Truncates without exception
'' + decimal.intValue() == decimalAsBigIntString
//BAD: Throws ArithmeticException 'Non-zero decimal digits' because we lose information
// decimal.intValueExact() == decimalAsBigIntString
//GOOD: Truncates without exception
'' + decimal.setScale(0, RoundingMode.DOWN).intValueExact() == decimalAsBigIntString
and: 'truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception'
//BAD: hugeDecimal.intValue() is -2147483648 instead of 2147483648
//'' + hugeDecimal.intValue() == hugeDecimalAsBigIntString
//BAD: Throws ArithmeticException 'Non-zero decimal digits' because we lose information
//'' + hugeDecimal.intValueExact() == hugeDecimalAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'' + hugeDecimal.setScale(0, RoundingMode.DOWN).intValueExact() == hugeDecimalAsBigIntString
and: 'truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception'
//BAD: hugeDecimal.intValue() is 0
//'' + reallyHuge.intValue() == reallyHugeAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'' + reallyHuge.intValueExact() == reallyHugeAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'' + reallyHuge.setScale(0, RoundingMode.DOWN).intValueExact() == reallyHugeAsBigIntString
and: 'if using Java 8, BigInteger has intValueExact() just like BigDecimal'
//decimal.toBigInteger().intValueExact() == decimal.setScale(0, RoundingMode.DOWN).intValueExact()
}