JDK 8附带所有令人眼前一亮的 东西 ( lambda表达式 , 流 , Optional ,新的Date / Time API等)来分散我的注意力 ,我并没有过多注意添加方法Math.toIntExact() 。 但是,这种小的添加本身可能会非常有用。
Math.toIntExact(long)的Javadoc文档指出:“返回long
参数的值; 如果值溢出int
则引发异常。” 这在给定或已经具有Long
且需要调用期望int
的API的情况下特别有用。 当然,最好是将API更改为使用相同的数据类型,但这有时是无法控制的。 当需要将Long
强制为int
值时,则存在整数溢出的可能性,因为Long
的数值可能比int
可以准确表示的数值大。
如果有人告诉给定的Long
永远不会大于int
可以容纳的Math.toIntExact(Long)
,则静态方法Math.toIntExact(Long)
尤其有用,因为如果出现这种“异常”情况,它将抛出未经检查的ArithmeticException ,这很明显发生“例外”情况。
当Long.intValue()用于从Long
获取整数时,如果发生整数溢出,则不会引发异常。 而是提供了一个整数,但是由于整数溢出,该值很少有用。 在几乎每种可能的情况下,遇到运行时异常都会向整数警报发出警报的情况要比让软件继续错误地使用溢出数更好。
如在示出之间的差异的第一步Long.intValue()
和Math.toIntExact(Long)
,下面的代码生成的范围内Long
为5的值小于Integer.MAX_VALUE的至5以上Integer.MAX_VALUE
。
包含Integer.MAX_VALUE
的Long
的生成范围
/*** Generate {@code Long}s from range of integers that start* before {@code Integer.MAX_VALUE} and end after that* maximum integer value.** @return {@code Long}s generated over range includes* {@code Integer.MAX_VALUE}.*/
public static List<Long> generateLongInts()
{final Long maximumIntegerAsLong = Long.valueOf(Integer.MAX_VALUE);final Long startingLong = maximumIntegerAsLong - 5;final Long endingLong = maximumIntegerAsLong + 5;return LongStream.range(startingLong, endingLong).boxed().collect(Collectors.toList());
}
下一个代码清单显示了两种方法,这些方法演示了前面提到的两种从Long
获取int
方法。
使用Long.intValue()
和Math.toIntExact(Long)
/*** Provides the {@code int} representation of the provided* {@code Long} based on an invocation of the provided* {@code Long} object's {@code intValue()} method.** @param longRepresentation {@code Long} for which {@code int}* value extracted with {@code intValue()} will be returned.* @return {@code int} value corresponding to the provided* {@code Long} as provided by invoking the method* {@code intValue()} on that provided {@code Long}.* @throws NullPointerException Thrown if the provided long* representation is {@code null}.*/
public static void writeLongIntValue(final Long longRepresentation)
{out.print(longRepresentation + " => Long.intValue() = ");try{out.println(longRepresentation.intValue());}catch (Exception exception){out.println("ERROR - " + exception);}
}/*** Provides the {@code int} representation of the provided* {@code Long} based on an invocation of {@code Math.toIntExact(Long)}* on the provided {@code Long}.** @param longRepresentation {@code Long} for which {@code int}* value extracted with {@code Math.toIntExact(Long)} will be* returned.* @return {@code int} value corresponding to the provided* {@code Long} as provided by invoking the method* {@code Math.toIntExact)Long} on that provided {@code Long}.* @throws NullPointerException Thrown if the provided long* representation is {@code null}.* @throws ArithmeticException Thrown if the provided {@code Long}* cannot be represented as an integer without overflow.*/
public static void writeIntExact(final Long longRepresentation)
{out.print(longRepresentation + " => Math.toIntExact(Long) = ");try{out.println(Math.toIntExact(longRepresentation));}catch (Exception exception){out.println("ERROR: " + exception);}
}
当以上代码使用在先前代码清单中构建的Long
的范围( GitHub上提供完整代码 )执行时,输出如下所示:
2147483642 => Long.intValue() = 2147483642
2147483642 => Math.toIntExact(Long) = 2147483642
2147483643 => Long.intValue() = 2147483643
2147483643 => Math.toIntExact(Long) = 2147483643
2147483644 => Long.intValue() = 2147483644
2147483644 => Math.toIntExact(Long) = 2147483644
2147483645 => Long.intValue() = 2147483645
2147483645 => Math.toIntExact(Long) = 2147483645
2147483646 => Long.intValue() = 2147483646
2147483646 => Math.toIntExact(Long) = 2147483646
2147483647 => Long.intValue() = 2147483647
2147483647 => Math.toIntExact(Long) = 2147483647
2147483648 => Long.intValue() = -2147483648
2147483648 => Math.toIntExact(Long) = ERROR: java.lang.ArithmeticException: integer overflow
2147483649 => Long.intValue() = -2147483647
2147483649 => Math.toIntExact(Long) = ERROR: java.lang.ArithmeticException: integer overflow
2147483650 => Long.intValue() = -2147483646
2147483650 => Math.toIntExact(Long) = ERROR: java.lang.ArithmeticException: integer overflow
2147483651 => Long.intValue() = -2147483645
2147483651 => Math.toIntExact(Long) = ERROR: java.lang.ArithmeticException: integer overflow
高亮显示的行指示代码处理Long
的值等于Integer.MAX_VALUE
的代码。 之后,显示的Long
表示比Integer.MAX_VALUE
多一个的Long
并显示尝试使用Long.intValue()
和Math.toIntExact(Long)
将该Long
转换为int
的结果。 Long.intValue()
方法遇到整数溢出,但不会引发异常,而是返回负数-2147483648 。 Math.toIntExact(Long)
方法在整数溢出时不返回任何值,而是引发ArithmeticException
与信息性消息“整数溢出”。
Math.toIntExact(Long)
方法的重要性不如JDK 8引入的许多功能重要,但是它对于避免有时可能难以诊断的整数溢出相关的错误类型很有用。
翻译自: https://www.javacodegeeks.com/2018/06/exact-conversion-long-to-int-java.html