parse - Casting seguro largo a int en Java
round double to int java (10)
Afirmo que la forma obvia de ver si la conversión de un valor cambió el valor sería emitir y verificar el resultado. Sin embargo, eliminaría el lanzamiento innecesario al comparar. Tampoco estoy demasiado interesado en los nombres de las variables de una letra (excepción x
e y
, pero no cuando significan fila y columna (a veces respectivamente)).
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;
}
Sin embargo, realmente me gustaría evitar esta conversión si es posible. Obviamente, a veces no es posible, pero en esos casos, IllegalArgumentException
es casi con toda seguridad la excepción errónea que se debe lanzar en lo que respecta al código del cliente.
¿Cuál es la forma más idiomática en Java para verificar que una conversión de long
a int
no pierde ninguna información?
Esta es mi implementación actual:
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;
}
Aquí hay una solución, en caso de que no te importe el valor en caso de que sea más grande de lo necesario;)
public static int safeLongToInt(long l) {
return (int) Math.max(Math.min(Integer.MAX_VALUE, l), Integer.MIN_VALUE);
}
Con BigDecimal:
long aLong = ...;
int anInt = new BigDecimal(aLong).intValueExact(); // throws ArithmeticException
// if outside bounds
Con la clase Ints Google Guava, su método se puede cambiar a:
public static int safeLongToInt(long l) {
return Ints.checkedCast(l);
}
De los documentos vinculados:
verificado
public static int checkedCast(long value)
Devuelve el valor int que es igual al
value
, si es posible.Parámetros:
value
- cualquier valor en el rango del tipoint
Devuelve: el valor
int
que es igual alvalue
Emite:
IllegalArgumentException
- si elvalue
es mayor queInteger.MAX_VALUE
o menor queInteger.MIN_VALUE
Por cierto, no necesita el envoltorio safeLongToInt
, a menos que desee dejarlo en su lugar para cambiar la funcionalidad sin una refactorización extensa, por supuesto.
Creo que lo haría tan simple como:
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;
}
Creo que eso expresa la intención más claramente que el reparto repetido ... pero es algo subjetivo.
Nota de interés potencial: en C # simplemente sería:
return checked ((int) l);
Los tipos enteros de Java se representan como firmados. Con una entrada entre 2 31 y 2 32 (o -2 31 y -2 32 ) la conversión tendría éxito pero su prueba fallaría.
Lo que hay que verificar es si todos los bits altos del long
son todos iguales:
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("...");
}
}
Otra solución puede ser:
public int longToInt(Long longVariable)
{
try {
return Integer.valueOf(longVariable.toString());
} catch(IllegalArgumentException e) {
Log.e(e.printstackstrace());
}
}
He intentado esto en los casos en los que el cliente realiza una POST y la base de datos del servidor solo comprende enteros mientras que el cliente tiene un valor largo.
Se ha agregado un nuevo método con Java 8 para hacer precisamente eso.
import static java.lang.Math.toIntExact;
long foo = 10L;
int bar = toIntExact(foo);
Lanzará una ArithmeticException
en caso de desbordamiento.
Varios otros métodos seguros de desbordamiento se han agregado a Java 8. Terminan con exacto .
Ejemplos:
-
Math.incrementExact(long)
-
Math.subtractExact(long, long)
-
Math.decrementExact(long)
-
Math.negateExact(long),
-
Math.subtractExact(int, int)
NO: ¡Esto no es una solución!
Mi primer acercamiento fue:
public int longToInt(long theLongOne) {
return Long.valueOf(theLongOne).intValue();
}
Pero eso simplemente convierte el largo en un int, potencialmente creando nuevas instancias de Long
o recuperándolas del Long pool.
Los inconvenientes
Long.valueOf
crea una nueva instancia deLong
si el número no está dentro del rango de la agrupación deLong
[-128, 127].La implementación de
intValue
no hace nada más que:return (int)value;
Por lo tanto, esto puede considerarse incluso peor que simplemente lanzar el long
al int
.
(int) (longType + 0)
pero largo no puede exceder el máximo :)