Java中Long到Int的精确转换

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_VALUELong的生成范围

/**
 * 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()方法遇到整数溢出,但不会引发异常,而是返回负数-2147483648Math.toIntExact(Long)方法在整数溢出时不返回任何值,而是引发ArithmeticException与信息性消息“整数溢出”。

Math.toIntExact(Long)方法的重要性不如JDK 8引入的许多功能重要,但它对于避免与整数溢出相关的错误类型(可能有时难以诊断)非常有用。

翻译自: https://www.javacodegeeks.com/2018/06/exact-conversion-long-to-int-java.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值