我有一个返回BigDecimal的Hibernate方法。
我有另一个API方法,我需要传递该数字,但它接受整数作为参数。我无法更改这两个方法的返回类型或变量类型。
现在该如何将BigDecimal转换为Integer并将其传递给第二个方法呢?
是否有解决办法?
我有一个返回BigDecimal的Hibernate方法。
我有另一个API方法,我需要传递该数字,但它接受整数作为参数。我无法更改这两个方法的返回类型或变量类型。
现在该如何将BigDecimal转换为Integer并将其传递给第二个方法呢?
是否有解决办法?
您可以调用 myBigDecimal.intValueExact()
(或者只是intValue()
),如果会丢失信息,它甚至会抛出异常。这将返回一个int,但自动装箱会处理它。
intValueExact()
是一个很好的建议;它在1.5中被添加。 - AnonintValue()
是危险的,除非你百分之百确定该数字在 Integer
范围内。 - Snekse您能保证 BigDecimal
永远不会包含大于 Integer.MAX_VALUE
的值吗?
如果是的话,那么这是调用intValue
的代码:
Integer.valueOf(bdValue.intValue())
简而言之:
使用以下任一工具进行通用转换需求
//Java 7 or below
bigDecimal.setScale(0, RoundingMode.DOWN).intValueExact()
//Java 8
bigDecimal.toBigInteger().intValueExact()
推理
答案取决于要求是什么以及你如何回答这些问题。
BigDecimal
可能有非零小数部分吗?BigDecimal
可能不适合 Integer
范围吗?如果您对前两个问题的回答是否,则可以像其他人建议的那样使用 BigDecimal.intValueExact()
,让它在发生意外情况时崩溃。
如果您对问题2不绝对有 100%的把握,那么intValue()
永远都是错误的答案。
改进
让我们基于其他答案使用以下假设。
intValueExact()
和自动装箱所做的BigDecimal
大于 Integer
范围时,我们希望抛出异常,因为除非您有非常特定的需要,否则任何其他情况都会很疯狂,因为您删除高阶位时发生了环绕。在这些参数下,如果我们的小数部分非零,intValueExact()
会在不希望它抛出异常时抛出异常。另一方面,如果我们的 BigDecimal
太大,则 intValue()
不会在应该抛出异常时抛出异常。
要同时获得两全其美的效果,先四舍五入 BigDecimal
,然后再进行转换。这也有助于更好地控制舍入过程。
Spock Groovy测试
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()
}
你可以调用 BigDecimal.intValue()
方法:
将此 BigDecimal 对象转换为 int。此转换类似于 Java 语言规范中定义的从 double 到 short 的缩小原始转换:此 BigDecimal 的任何小数部分都将被舍弃,如果生成的“BigInteger”太大而无法适应 int,则仅返回低位32位。请注意,此转换可能会丢失有关此 BigDecimal 值的总体大小和精度的信息,并返回相反符号的结果。
然后你可以显式调用 Integer.valueOf(int)
或者让自动装箱在使用足够新的 Java 版本时自动完成。
BigDecimal d = new BigDecimal(10);
int i = d.intValue();
我发现上述方法对我不起作用。我正在从JTable中提取单元格值,但无法转换为double或int等。我的解决方案:
Object obj = getTable().getValueAt(row, 0);
第0行始终是一个数字。希望这能帮助那些仍在滚动的人!