在Java中安全地将long转换为int

Java中最习惯的方式是validation从longint不会丢失任何信息?

这是我目前的实现:

 public static int safeLongToInt(long l) { int i = (int)l; if ((long)i != l) { throw new IllegalArgumentException(l + " cannot be cast to int without changing its value."); } return i; } 

Java 8增加了一个新的方法来做到这一点。

 import static java.lang.Math.toIntExact; long foo = 10L; int bar = toIntExact(foo); 

在溢出的情况下会抛出一个ArithmeticException。

请参阅: Math.toIntExact(long)

其他几种溢出安全方法已经被添加到Java 8中。

例子:

  • Math.incrementExact(long)
  • Math.subtractExact(long, long)
  • Math.decrementExact(long)
  • Math.negateExact(long),
  • Math.subtractExact(int, int)

我想我会这样做:

 public static int safeLongToInt(long l) { if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) { throw new IllegalArgumentException (l + " cannot be cast to int without changing its value."); } return (int) l; } 

我认为比反复演绎更清楚地expression意图……但是这有点主观。

注意潜在的兴趣 – 在C#中它只是:

 return checked ((int) l); 

使用Google Guava的Ints类,您的方法可以更改为:

 public static int safeLongToInt(long l) { return Ints.checkedCast(l); } 

从链接的文档:

checkedCast时

public static int checkedCast(long value)

如果可能,返回等于value的int值。

参数: valueinttypes范围内的任何值

返回:等于valueint value

抛出: IllegalArgumentException – 如果value大于Integer.MAX_VALUE或小于Integer.MIN_VALUE

顺便说一句,你不需要safeLongToInt包装器,除非你想保持原来的function,而不需要大量的重构。

使用BigDecimal:

 long aLong = ...; int anInt = new BigDecimal(aLong).intValueExact(); // throws ArithmeticException // if outside bounds 

这里是一个解决scheme,如果你不关心价值的情况下,那么它是需要的;)

 public static int safeLongToInt(long l) { return (int) Math.max(Math.min(Integer.MAX_VALUE, l), Integer.MIN_VALUE); } 

我声称显而易见的方式来看看是否铸造一个值改变了价值将是铸造和检查结果。 但是,我会在比较时删除不必要的投射。 我也不太热衷于一个字母variables的名字(例外xy ,但不是当他们的意思是行和列(有时分别))。

 public static int intValue(long value) { int valueInt = (int)value; if (valueInt != value) { throw new IllegalArgumentException( "The long value "+value+" is not within range of the int type" ); } return valueInt; } 

但是,如果可能的话,我真的想避免这种转换。 显然有时候这是不可能的,但在这种情况下,就客户代码而言, IllegalArgumentException几乎肯定是抛出的exception。

不要:这不是一个解决scheme!

我的第一个方法是:

 public int longToInt(long theLongOne) { return Long.valueOf(theLongOne).intValue(); } 

但是,这只是将long转换为int,可能会创build新的Long实例或从Long池中检索它们。


缺点

  1. Long.valueOf创build一个新的Long实例,如果该数字不在Long的池范围内[-128,127]。

  2. intValue实现只不过是:

     return (int)value; 

所以这可以被认为比仅仅把long int变成更糟。

Java整数types被表示为signed。 input介于2 31和2 32 (或-2 31和-2 32 )之间时,演员将成功,但是您的testing将失败。

要检查的是所有的高位是否都是一样的:

 public static final long LONG_HIGH_BITS = 0xFFFFFFFF80000000L; public static int safeLongToInt(long l) { if ((l & LONG_HIGH_BITS) == 0 || (l & LONG_HIGH_BITS) == LONG_HIGH_BITS) { return (int) l; } else { throw new IllegalArgumentException("..."); } } 
 (int) (longType + 0) 

但龙不能超过最高:)

另一个解决scheme可以是:

 public int longToInt(Long longVariable) { try { return Integer.valueOf(longVariable.toString()); } catch(IllegalArgumentException e) { Log.e(e.printstackstrace()); } } 

我已经尝试了这种情况下,客户端正在做一个POST和服务器DB理解只有整数,而客户端有一个长。