Bool
第一行返回-5但第二行抛出异常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));
这是方法java.lang.IllegalArgumentException: Could not convert number [18446744073709551611] of type [java.math.BigDecimal] to target class [java.lang.Long]: overflow
的预期结果吗?
答案 0 :(得分:2)
这是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和然后检查此长值是否在类型的范围内,它首先需要longValue
。但是,如果它不在长值的范围内,则长值是截断的数字,这是无意义的并且可能看起来在较小类型的范围内,但实际上并不是因为最高位是在初始转换为long时被截断。
在您的示例中,18446744073709551611截断为Long得到-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,然后检查范围,然后转换为正确type(整数/字节/短)。
答案 1 :(得分:0)
这是方法的预期结果
是和否。
是的,这是指定java.lang.Long
并获得Long溢出的预期结果。
不,通常,因为根据方法签名convertNumberToTargetClass(Number number, Class targetClass)
,如果targetClass
是java.lang.Number
的子类,那么您不会得到此异常。在你的情况下,java.lang.Long
是子类,所以它不会出现,但是你因为溢出而得到了。
来自org.springframework.util.NumberUtils.convertNumberToTargetClass
public static <T extends Number> T convertNumberToTargetClass(Number number, Class<T> targetClass) throws IllegalArgumentException {
......
else if (targetClass.equals(Long.class)) {
BigInteger bigInt = null;
if (number instanceof BigInteger) {
bigInt = (BigInteger) number;
}
else if (number instanceof BigDecimal) {
bigInt = ((BigDecimal) number).toBigInteger();
}
// Effectively analogous to JDK 8's BigInteger.longValueExact()
if (bigInt != null && (bigInt.compareTo(LONG_MIN) < 0 || bigInt.compareTo(LONG_MAX) > 0)) {
raiseOverflowException(number, targetClass);
}
return (T) new Long(number.longValue());
}
.......
}
以下是raiseOverflowException
的代码段,从您获得例外的地方开始:
private static void [More ...] raiseOverflowException(Number number, Class<?> targetClass) {
throw new IllegalArgumentException("Could not convert number [" + number + "] of type [" +
number.getClass().getName() + "] to target class [" + targetClass.getName() + "]: overflow");
}
查看org.springframework.util.NumberUtils.convertNumberToTargetClass
here