在 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
Safely casting long to int in Java
提问by Brigham
What's the most idiomatic way in Java to verify that a cast from long
to int
does not lose any information?
Java 中验证从long
to 的转换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 ArithmeticException
in case of overflow.
ArithmeticException
在溢出的情况下会抛出一个。
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 long
are 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 x
and y
, but not when they mean row and column (sometimes respectively)).
我声称,查看强制转换值是否改变了值的显而易见的方法是强制转换并检查结果。但是,我会在比较时删除不必要的演员表。我也不太热衷于一个字母的变量名(例外x
and 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 IllegalArgumentException
is 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 theint
typeReturns:the
int
value that equalsvalue
Throws:
IllegalArgumentException
- ifvalue
is greater thanInteger.MAX_VALUE
or less thanInteger.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 safeLongToInt
wrapper, 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 Long
instances or retrieving them from the Long pool.
但这只是将 long 转换为 int,可能会创建新Long
实例或从 Long 池中检索它们。
The drawbacks
缺点
Long.valueOf
creates a newLong
instance if the number is not withinLong
's pool range [-128, 127].The
intValue
implementation does nothing more than:return (int)value;
Long.valueOf
Long
如果数字不在Long
的池范围 [-128, 127]内,则创建一个新实例。该
intValue
执行不执行任何超过:return (int)value;
So this can be considered even worse than just casting the long
to int
.
所以这可以被认为比仅仅投射long
to更糟糕int
。