为什么在Spring Boot framework源代码中将"Number"转换为"Float"或"Double"时不检查范围溢出
Why don't check the range overflow when converting "Number" to "Float" or "Double" in Spring Boot framework source code
请查看来自org.springframework.util.NumberUtils#convertNumberToTargetClass()
的源代码片段,方法签名是+ <T extends Number> T convertNumberToTargetClass(number:Number, targetClass:Class<?>)
public static <T extends Number> T convertNumberToTargetClass(Number number, Class<T> targetClass)
throws IllegalArgumentException {
... ...
... ...
else if (Float.class == targetClass) {
return (T) Float.valueOf(number.floatValue());
}
.... ....
.... ....
}
将number
转换为Float
时,不检查number
是否超出Float
的范围。但它会检查将数字转换为 Byte
、Integer
或 Short
时,如下所示:
public static <T extends Number> T convertNumberToTargetClass(Number number, Class<T> targetClass)
throws IllegalArgumentException {
... ...
... ...
else if (Byte.class == targetClass) {
long value = checkedLongValue(number, targetClass);
if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
raiseOverflowException(number, targetClass);
}
return (T) Byte.valueOf(number.byteValue());
}
... ...
... ...
}
private static long checkedLongValue(Number number, Class<? extends Number> targetClass) {
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 number.longValue();
}
private static void raiseOverflowException(Number number, Class<?> targetClass) {
throw new IllegalArgumentException("Could not convert number [" + number + "] of type [" +
number.getClass().getName() + "] to target class [" + targetClass.getName() + "]: overflow");
}
我很好奇为什么!
因为没有溢出。
如果你这样做:
Float aFloat = NumberUtils.convertNumberToTargetClass(Double.MAX_VALUE, Float.class);
aFloat 的值将为 Infinity。
查看 API 文档:https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Float.html
请查看来自org.springframework.util.NumberUtils#convertNumberToTargetClass()
的源代码片段,方法签名是+ <T extends Number> T convertNumberToTargetClass(number:Number, targetClass:Class<?>)
public static <T extends Number> T convertNumberToTargetClass(Number number, Class<T> targetClass)
throws IllegalArgumentException {
... ...
... ...
else if (Float.class == targetClass) {
return (T) Float.valueOf(number.floatValue());
}
.... ....
.... ....
}
将number
转换为Float
时,不检查number
是否超出Float
的范围。但它会检查将数字转换为 Byte
、Integer
或 Short
时,如下所示:
public static <T extends Number> T convertNumberToTargetClass(Number number, Class<T> targetClass)
throws IllegalArgumentException {
... ...
... ...
else if (Byte.class == targetClass) {
long value = checkedLongValue(number, targetClass);
if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
raiseOverflowException(number, targetClass);
}
return (T) Byte.valueOf(number.byteValue());
}
... ...
... ...
}
private static long checkedLongValue(Number number, Class<? extends Number> targetClass) {
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 number.longValue();
}
private static void raiseOverflowException(Number number, Class<?> targetClass) {
throw new IllegalArgumentException("Could not convert number [" + number + "] of type [" +
number.getClass().getName() + "] to target class [" + targetClass.getName() + "]: overflow");
}
我很好奇为什么!
因为没有溢出。
如果你这样做:
Float aFloat = NumberUtils.convertNumberToTargetClass(Double.MAX_VALUE, Float.class);
aFloat 的值将为 Infinity。
查看 API 文档:https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Float.html