首页 文章

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

提问于
浏览
423

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

10 回答

  • -6
    (int) (longType + 0)
    

    但龙不能超过最大:)

  • 126

    我想我会这样做:

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

    使用BigDecimal:

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

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

    使用 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)

  • 0

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

  • 300

    DONT: This is not a solution!

    我的第一个方法是:

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

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


    缺点

    如果数字不在 Long 的池范围内,则

    • Long.valueOf 会创建一个新的 Long 实例[-128,127] .

    • intValue 实现只做以下事情:

    return (int)value;
    

    所以这可以被认为比仅仅将 long 转换为 int 更糟糕 .

  • 10

    另一个解决方案可以是:

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

    我已经尝试过这种情况,因为客户端正在执行POST,而服务器数据库只能理解整数,而客户端只有Long .

  • 476

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

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

    来自链接的文档:

    checkedCast public static int checkedCast(long value)如果可能,返回等于value的int值 . 参数:value - int类型范围内的任何值返回:等于value的int值抛出:IllegalArgumentException - 如果value大于Integer.MAX_VALUE或小于Integer.MIN_VALUE

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

  • 7

    这是一个解决方案,万一你不关心 Value ,以防它需要更大;)

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

相关问题