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

Java中验证从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;
}
614620 次浏览

我想我会这么简单:

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;
}

我认为这比反复选角更清楚地表达了意图……但这有点主观。

注意,潜在的兴趣-在c#中,它只是:

return checked ((int) l);

Java整数类型表示为有符号。如果输入在231和232之间(或-231和-232),强制转换将成功,但测试将失败。

要检查的是long的所有高位是否都相同:

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("...");
}
}

我认为,要查看强制转换是否改变了值,最明显的方法是强制转换并检查结果。但是,在比较时,我会删除不必要的强制转换。我也不太热衷于一个字母的变量名(例外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几乎肯定是应该抛出的错误异常。

使用谷歌Guava的整数类,您的方法可以更改为:

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

从链接的文档:

checkedCast

# EYZ0

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

< >强参数: value - int类型范围内的任何值

< >强劲的回报: = value

int

< >强投: IllegalArgumentException -如果value大于Integer.MAX_VALUE或小于Integer.MIN_VALUE

顺便说一句,您不需要safeLongToInt包装器,除非您想保留它,以便在不进行大量重构的情况下更改功能。

另一个解决方案是:

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

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

这里有一个解决方案,以防你不关心值,以防它比需要的更大;)

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

BigDecimal:

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

但Long不能超过最大值:)

这不是解决方案!

我的第一个方法是:

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

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


的缺点

  1. 如果编号不在Long的池范围[-128,127]内,Long.valueOf将创建一个新的Long实例。

  2. intValue实现所做的只是:

    return (int)value;
    

So this can be considered even worse than just casting the long to int.

使用Java 8添加了一个新方法来完成这项工作。

import static java.lang.Math.toIntExact;


long foo = 10L;
int bar = toIntExact(foo);

如果溢出,将抛出ArithmeticException

看到:# EYZ1

Java 8中还添加了其他几个溢出安全方法。它们以确切的结尾。

例子:

  • # EYZ0
  • # EYZ0
  • # EYZ0
  • # EYZ0
  • # EYZ0