What's the most idiomatic way in Java to verify that a cast from long
to int
does not lose any information?
在Java中,什么是最惯用的方法来验证从long到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;
}
10 个解决方案
#1
377
A new method has been added with Java 8 to 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.
在溢出时将抛出一个算术异常。
看到:Math.toIntExact(长)
Several other overflow safe methods have been added to Java 8. They end with exact.
Java 8还添加了其他一些溢出安全方法。他们用准确的结束。
Examples:
例子:
Math.incrementExact(long)
- Math.incrementExact(长)
Math.subtractExact(long, long)
- 数学。subtractExact(长)
Math.decrementExact(long)
- Math.decrementExact(长)
Math.negateExact(long),
- Math.negateExact(长),
Math.subtractExact(int, int)
- 数学。subtractExact(int,int)
#2
292
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);
#3
123
With Google Guava's Ints class, your method can be changed to:
使用谷歌Guava的Ints类,你的方法可以改为:
public static int safeLongToInt(long l) {
return Ints.checkedCast(l);
}
From the linked docs:
相关文档:
checkedCast
public static int checkedCast(long value)
public static int checkedCast(长值)
Returns the int value that is equal to
value
, if possible.如果可能,返回等于值的int值。
Parameters:
value
- any value in the range of theint
type参数:值—int类型范围内的任何值。
Returns: the
int
value that equalsvalue
返回:等于值的int值。
Throws:
IllegalArgumentException
- ifvalue
is greater thanInteger.MAX_VALUE
or less thanInteger.MIN_VALUE
抛出:IllegalArgumentException——如果值大于整数。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.
顺便说一下,您不需要safextentoint包装器,除非您想让它在不需要进行大规模重构的情况下更改功能。
#4
25
With BigDecimal:
BigDecimal:
long aLong = ...;
int anInt = new BigDecimal(aLong).intValueExact(); // throws ArithmeticException
// if outside bounds
#5
13
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);
}
#6
9
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类型,可能会创建新的长实例,或者从长池中检索它们。
The drawbacks
的缺点
-
Long.valueOf
creates a newLong
instance if the number is not withinLong
's pool range [-128, 127].长。valueOf创建一个新的长实例,如果数字不在Long的池范围内[-128,127]。
-
The
intValue
implementation does nothing more than:intValue实现所做的仅仅是:
return (int)value;
So this can be considered even worse than just casting the long
to int
.
因此,这可以被认为比仅仅把长时间转换为int更糟糕。
#7
7
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和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几乎肯定是错误的,因为客户端代码是错误的。
#8
2
Java integer types are represented as signed. With an input between 231 and 232 (or -231 and -232) the cast would succeed but your test would fail.
Java整数类型表示为已签名。在231和232(或-231和-232)之间输入,cast将成功,但是您的测试将失败。
What to check for is whether all of the high bits of the long
are all the same:
要检查的是所有的高比特是否都是一样的:
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("...");
}
}
#9
0
(int) (longType + 0)
but Long can not exceed the maximum :)
但长不能超过最大:)
#10
-5
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只理解整数,而客户端有很长时间。
#1
377
A new method has been added with Java 8 to 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.
在溢出时将抛出一个算术异常。
看到:Math.toIntExact(长)
Several other overflow safe methods have been added to Java 8. They end with exact.
Java 8还添加了其他一些溢出安全方法。他们用准确的结束。
Examples:
例子:
Math.incrementExact(long)
- Math.incrementExact(长)
Math.subtractExact(long, long)
- 数学。subtractExact(长)
Math.decrementExact(long)
- Math.decrementExact(长)
Math.negateExact(long),
- Math.negateExact(长),
Math.subtractExact(int, int)
- 数学。subtractExact(int,int)
#2
292
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);
#3
123
With Google Guava's Ints class, your method can be changed to:
使用谷歌Guava的Ints类,你的方法可以改为:
public static int safeLongToInt(long l) {
return Ints.checkedCast(l);
}
From the linked docs:
相关文档:
checkedCast
public static int checkedCast(long value)
public static int checkedCast(长值)
Returns the int value that is equal to
value
, if possible.如果可能,返回等于值的int值。
Parameters:
value
- any value in the range of theint
type参数:值—int类型范围内的任何值。
Returns: the
int
value that equalsvalue
返回:等于值的int值。
Throws:
IllegalArgumentException
- ifvalue
is greater thanInteger.MAX_VALUE
or less thanInteger.MIN_VALUE
抛出:IllegalArgumentException——如果值大于整数。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.
顺便说一下,您不需要safextentoint包装器,除非您想让它在不需要进行大规模重构的情况下更改功能。
#4
25
With BigDecimal:
BigDecimal:
long aLong = ...;
int anInt = new BigDecimal(aLong).intValueExact(); // throws ArithmeticException
// if outside bounds
#5
13
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);
}
#6
9
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类型,可能会创建新的长实例,或者从长池中检索它们。
The drawbacks
的缺点
-
Long.valueOf
creates a newLong
instance if the number is not withinLong
's pool range [-128, 127].长。valueOf创建一个新的长实例,如果数字不在Long的池范围内[-128,127]。
-
The
intValue
implementation does nothing more than:intValue实现所做的仅仅是:
return (int)value;
So this can be considered even worse than just casting the long
to int
.
因此,这可以被认为比仅仅把长时间转换为int更糟糕。
#7
7
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和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几乎肯定是错误的,因为客户端代码是错误的。
#8
2
Java integer types are represented as signed. With an input between 231 and 232 (or -231 and -232) the cast would succeed but your test would fail.
Java整数类型表示为已签名。在231和232(或-231和-232)之间输入,cast将成功,但是您的测试将失败。
What to check for is whether all of the high bits of the long
are all the same:
要检查的是所有的高比特是否都是一样的:
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("...");
}
}
#9
0
(int) (longType + 0)
but Long can not exceed the maximum :)
但长不能超过最大:)
#10
-5
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只理解整数,而客户端有很长时间。