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

问题描述 投票:450回答:10

在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;
}
java casting
10个回答
522
投票

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)

-6
投票

另一个解决方案可以是:

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

我已经尝试过这种情况,客户端正在进行POST,而服务器数据库只能理解Integers,而客户端只有Long。


302
投票

我想我会这样做:

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

128
投票

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

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

来自链接的文档:

checkedCast时

public static int checkedCast(long value)

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

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

返回:int值等于value

投掷:IllegalArgumentException - 如果value大于Integer.MAX_VALUE或小于Integer.MIN_VALUE

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


29
投票

使用BigDecimal:

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

16
投票

这是一个解决方案,如果你不关心价值,以防它需要更大;)

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

11
投票

不要:这不是解决方案!

我的第一个方法是:

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

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


缺点

  1. 如果数字不在Long.valueOf的游泳池范围内,Long会创建一个新的Long实例[-128,127]。
  2. intValue的实现只不过是: return (int)value;

因此,这可以被认为比仅仅将long投射到int更糟糕。


7
投票

我声称看到是否更改值的显而易见的方法是转换并检查结果。但是,我会在比较时删除不必要的演员表。我也不太热衷于一个字母变量名称(例外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几乎肯定是错误的例外。


2
投票

Java整数类型表示为signed。如果输入介于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("...");
    }
}

0
投票
(int) (longType + 0)

但龙不能超过最大值:)

© www.soinside.com 2019 - 2024. All rights reserved.