我有 Hibernate 方法,它返回一个 BigDecimal。我有另一个 API 方法,我需要将该数字传递给它,但它接受 Integer 作为参数。我无法更改这两种方法的返回类型或变量类型。
现在如何将 BigDecimal 转换为 Integer 并将其传递给第二种方法?
有没有办法解决这个问题?
我有 Hibernate 方法,它返回一个 BigDecimal。我有另一个 API 方法,我需要将该数字传递给它,但它接受 Integer 作为参数。我无法更改这两种方法的返回类型或变量类型。
现在如何将 BigDecimal 转换为 Integer 并将其传递给第二种方法?
有没有办法解决这个问题?
你会打电话myBigDecimal.intValueExact()
(或只是intValue()
),如果你会丢失信息,它甚至会抛出异常。这会返回一个 int 但自动装箱会处理这个问题。
你能保证BigDecimal
永远不会包含大于 的值Integer.MAX_VALUE
吗?
如果是,那么这是您的代码调用intValue
:
Integer.valueOf(bdValue.intValue())
TL;博士
使用其中之一满足通用转换需求
//Java 7 or below
bigDecimal.setScale(0, RoundingMode.DOWN).intValueExact()
//Java 8
bigDecimal.toBigInteger().intValueExact()
推理
答案取决于要求是什么以及您如何回答这些问题。
BigDecimal
一个非零的小数部分吗?BigDecimal
可能不适合该Integer
范围吗?如果您对前 2 个问题的回答为“否”,则可以BigDecimal.intValueExact()
按照其他人的建议使用,并在发生意外情况时让它爆炸。
如果您对第 2 个问题不是绝对 100%有信心,那么答案总是错误的intValue()
。
让它变得更好
让我们根据其他答案使用以下假设。
intValueExact()
自动装箱的作用BigDecimal
我们希望在大于范围时抛出异常,Integer
因为除非您对丢弃高位位时发生的回绕有非常特殊的需求,否则其他任何事情都会很疯狂。给定这些参数,intValueExact()
如果我们的小数部分不为零,则在我们不希望它发生时抛出异常。另一方面,如果 our太大,intValue()
则不会在应该抛出异常时抛出异常。BigDecimal
为了两全其美,先完成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,则只有低-order 32 位被返回。请注意,此转换可能会丢失有关此 BigDecimal 值的总体大小和精度的信息,并返回带有相反符号的结果。
Integer.valueOf(int)
然后,如果您使用的是足够新的 Java 版本,则可以显式调用或让自动装箱为您执行此操作。
以下应该可以解决问题:
BigDecimal d = new BigDecimal(10);
int i = d.intValue();
您是否尝试过调用BigInteger#intValue()?
我发现上述方法对我不起作用。我正在从 JTable 中提取单元格值,但无法转换为 double 或 int 等。我的解决方案:
Object obj = getTable().getValueAt(row, 0);
其中第 0 行始终是一个数字。希望这对仍在滚动的人有所帮助!