繁体   English   中英

避免Instant.toEpochMilli()算法溢出

[英]Avoid Instant.toEpochMilli() Arithmetic Overflow

调用JDK Instant.toEpochMilli()可能会导致算术上溢/下溢(例如Instant.MAX.toEpochMilli()Instant.MIN.toEpochMilli() )。 我正在寻找一种避免算术溢出的简单方法,而只需使用Long.MAX_VALUE 这是我当前的代码。

long seconds, millis;

seconds = deadline.getEpochSecond();

if (seconds > Long.MAX_VALUE / 1000 - 1)
   millis = Long.MAX_VALUE;
else if (seconds < Long.MIN_VALUE / 1000 + 1)
   millis = Long.MIN_VALUE;
else
   millis = deadline.toEpochMilli();

似乎必须有一种更简洁的方法来实现此目的。 您将如何实现这种逻辑?

我必须担心上溢/下溢,因为Instant.MAXInstant.MIN传递给了此代码所在的方法。

您可以使用java.lang.Math.addExact 如果发生溢出,它将抛出ArithmeticException 它是在Java 8中添加的。

编辑

好的,再考虑这个问题,我认为我有一个不错的解决方案:

private Instant capped(Instant instant) {
    Instant[] instants = {Instant.ofEpochMilli(Long.MIN_VALUE), instant, Instant.ofEpochMilli(Long.MAX_VALUE)};
    Arrays.sort(instants);
    return instants[1];
}

此方法将返回一个Instant,它不会在toEpochMilli()上溢出。

将逻辑简化为:

millis = capped(deadline).toEpochMilli();

如果发生溢出, toEpochMilli会引发异常,因此您可以捕获该异常:

try {
  millis = deadline.toEpochMillis();
} catch (AritmeticException ignore) {
  millis = deadline.getEpochSecond() < 0 ? Long.MIN_VALUE : Long.MAX_VALUE;
}

此代码比问题中编写的代码更简单,更安全。 这比较安全,因为它不会尝试重新实现toEpochMillis()内部的边界逻辑。

引发和捕获异常可能存在性能问题。 这取决于引发异常的频率。 如果大多数时间都抛出异常,那么除非JVM可以对其进行优化,否则这将表现得更糟。 如果很少抛出异常,那么性能会很好。

JVM可能能够优化这一点,但也许没有。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM