java - NumberUtils 在将 BigDecimal 转换为 Long 时抛出异常,但在转换为 Integer 时成功

标签 java spring

System.out.println(org.springframework.util.NumberUtils.convertNumberToTargetClass(new BigDecimal("18446744073709551611"), Integer.class));
System.out.println(org.springframework.util.NumberUtils.convertNumberToTargetClass(new BigDecimal("18446744073709551611"), Long.class));

第一行返回 -5 但第二行抛出异常 java.lang.IllegalArgumentException: Could not convert number [18446744073709551611] of type [java.math.BigDecimal] to target class [java.lang.Long]: overflow

这是 org.springframework.util.NumberUtils.convertNumberToTargetClass 方法的预期结果吗?

最佳答案

这是 Spring 中的一个错误。

转换为 long 的边界检查是正确的。它首先将 BigDecimal 转换为 BigInteger,然后检查它是否在 Long 的范围内。

88      else if (targetClass.equals(Long.class)) {
89          BigInteger bigInt = null;
90          if (number instanceof BigInteger) {
91              bigInt = (BigInteger) number;
92          }
93          else if (number instanceof BigDecimal) {
94              bigInt = ((BigDecimal) number).toBigInteger();
95          }
96          // Effectively analogous to JDK 8's BigInteger.longValueExact()
97          if (bigInt != null && (bigInt.compareTo(LONG_MIN) < 0 || bigInt.compareTo(LONG_MAX) > 0)) {
98              raiseOverflowException(number, targetClass);
99          }
100         return (T) new Long(number.longValue());
101     }

然而,到 Integer(和其他原始数字类型)的转换被破坏了。 如果 BigDecimal 和 then 检查此 long 值是否在类型范围内,它首先采用 longValue。但是,如果它不在 long 值的范围内,则 long 值是一个无意义的截断数字,可能看起来在较小类型的范围内,但实际上并不是因为顶部位在初始转换为 long。

在您的示例中,18446744073709551611 被截断为 Long yield -5,这完全在整数范围内 - 但原始数字显然不在整数范围内。

81      else if (targetClass.equals(Integer.class)) {
82          long value = number.longValue();
83          if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
84              raiseOverflowException(number, targetClass);
85          }
86          return (T) new Integer(number.intValue());
87      }

为了正确实现这一点,Spring 需要将转换更改为 Integer(以及 Short 和 Byte)以与转换为 Long 的方式相同:首先转换为 BigInteger,然后检查范围,然后转换为正确的类型(整数/字节/短整型)。

关于java - NumberUtils 在将 BigDecimal 转换为 Long 时抛出异常,但在转换为 Integer 时成功,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35822941/

相关文章:

java - 如何序列化属性但不使用 spring 数据持久化它?

spring - 使用空字符串作为属性的默认值,以便可以将其与其他字符串连接以形成值

java - 一种表示某事已发生的方式

java - 每次页面加载后Xpath都会改变

java - 生成签名和加密的 JWT

java - 我们如何强制许多映射器读取 hadoop 中的一个特定文件(相同数据)?

java - 如何从表中获取用户名

java - Spring Tool Suite-引用项目

java - 重复的 Spring 属性文件

java - Jetty WebSockets ssl == null 错误