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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1590831/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 16:32:18  来源:igfitidea点击:

Safely casting long to int in Java

javacasting

提问by Brigham

What's the most idiomatic way in Java to verify that a cast from longto intdoes not lose any information?

Java 中验证从longto 的转换int不会丢失任何信息的最惯用的方法是什么?

This is my current implementation:

这是我目前的实现:

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

采纳答案by Pierre-Antoine

A new method has been added with Java 8to do just that.

Java 8 中添加了一个新方法来做到这一点。

import static java.lang.Math.toIntExact;

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

Will throw an ArithmeticExceptionin case of overflow.

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

See: Math.toIntExact(long)

看: Math.toIntExact(long)

Several other overflow safe methods have been added to Java 8. They end with exact.

其他几种溢出安全方法已添加到 Java 8 中。它们以精确.

Examples:

例子:

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

回答by Jon Skeet

I think I'd do it as simply as:

我想我会像这样简单地做:

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

I think that expresses the intent more clearly than the repeated casting... but it's somewhat subjective.

我认为这比重复投射更清楚地表达了意图……但这有点主观。

Note of potential interest - in C# it would just be:

潜在兴趣的注意事项 - 在 C# 中,它只是:

return checked ((int) l);

回答by mob

Java integer types are represented as signed. With an input between 231and 232(or -231and -232) the cast would succeed but your test would fail.

Java 整数类型表示为有符号的。输入介于 2 31和 2 32(或 -2 31和 -2 32)之间的输入会成功,但您的测试会失败。

What to check for is whether all of the high bits of the longare all the same:

要检查的是 的所有高位是否都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("...");
    }
}

回答by Tom Hawtin - tackline

I claim that the obvious way to see whether casting a value changed the value would be to cast and check the result. I would, however, remove the unnecessary cast when comparing. I'm also not too keen on one letter variable names (exception xand y, but not when they mean row and column (sometimes respectively)).

我声称,查看强制转换值是否改变了值的显而易见的方法是强制转换并检查结果。但是,我会在比较时删除不必要的演员表。我也不太热衷于一个字母的变量名(例外xand y,但不是当它们表示行和列(有时分别)时)。

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

However, really I would want to avoid this conversion if at all possible. Obviously sometimes it's not possible, but in those cases IllegalArgumentExceptionis almost certainly the wrong exception to be throwing as far as client code is concerned.

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

回答by prasopes

With Google Guava's Intsclass, your method can be changed to:

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

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

From the linked docs:

从链接的文档:

checkedCast

public static int checkedCast(long value)

Returns the int value that is equal to value, if possible.

Parameters:value- any value in the range of the inttype

Returns:the intvalue that equals value

Throws:IllegalArgumentException- if valueis greater than Integer.MAX_VALUEor less than Integer.MIN_VALUE

已选中

public static int checkedCast(long value)

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

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

返回:int等于 的值value

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

Incidentally, you don't need the safeLongToIntwrapper, unless you want to leave it in place for changing out the functionality without extensive refactoring of course.

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

回答by Rajat Anantharam

One other solution can be:

另一种解决方案可以是:

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

I have tried this for cases where the client is doing a POST and the server DB understands only Integers while the client has a Long.

我已经在客户端执行 POST 并且服务器 DB 只理解整数而客户端有一个 Long 的情况下尝试了这个。

回答by Vitaliy Kulikov

here is a solution, in case you don't care about value in case it is bigger then needed ;)

这是一个解决方案,以防万一您不关心价值,以防它比需要的大;)

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

回答by Jaime Saiz

With BigDecimal:

使用 BigDecimal:

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

回答by Maury

(int) (longType + 0)

but Long can not exceed the maximum :)

但 Long 不能超过最大值 :)

回答by Andreas

DONT: This is not a solution!

不要:这不是解决方案!

My first approach was:

我的第一种方法是:

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

But that merely just casts the long to an int, potentially creating new Longinstances or retrieving them from the Long pool.

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



The drawbacks

缺点

  1. Long.valueOfcreates a new Longinstance if the number is not within Long's pool range [-128, 127].

  2. The intValueimplementation does nothing more than:

    return (int)value;
    
  1. Long.valueOfLong如果数字不在Long的池范围 [-128, 127]内,则创建一个新实例。

  2. intValue执行不执行任何超过:

    return (int)value;
    

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

所以这可以被认为比仅仅投射longto更糟糕int