¿Cuál es la forma más idiomática en Java para verificar que un envío desde long
a int
no pierda 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;
}
Respuestas:
Se ha agregado un nuevo método con Java 8 para hacer precisamente eso.
Lanzará un
ArithmeticException
en caso de desbordamiento.Ver:
Math.toIntExact(long)
Se han agregado varios otros métodos seguros de desbordamiento a Java 8. Terminan con exacto .
Ejemplos:
Math.incrementExact(long)
Math.subtractExact(long, long)
Math.decrementExact(long)
Math.negateExact(long),
Math.subtractExact(int, int)
fuente
addExact
ymultiplyExact
. Es de destacar que la división (MIN_VALUE/-1
) y el valor absoluto (abs(MIN_VALUE)
) no tienen métodos de conveniencia seguros.Math.toIntExact()
lugar del yeso habitualint
? La implementación deMath.toIntExact()
solo echalong
aint
.Creo que lo haría tan simple como:
Creo que eso expresa la intención más claramente que el casting repetido ... pero es algo subjetivo.
Nota de interés potencial: en C # solo sería:
fuente
(!(Integer.MIN_VALUE <= l && l <= Integer.MAX_VALUE))
. Me resulta difícil entender otras formas de hacerlo. Lástima que Java no tieneunless
.int
.Con la clase Ints de Google Guava , su método se puede cambiar a:
De los documentos vinculados:
Por cierto, no necesita el
safeLongToInt
contenedor, a menos que desee dejarlo en su lugar para cambiar la funcionalidad sin una refactorización extensa, por supuesto.fuente
Ints.checkedCast
hace exactamente lo que hace OP, por ciertoInts.checkedCast(l)
directamente.Ints.saturatedCast
cuál devolverá el valor más cercano en lugar de lanzar una excepción.Con BigDecimal:
fuente
BigDecimal.valueOf(aLong)
, en lugar denew BigDecimal(aLong)
, denotar que no se requiere una nueva instancia. Si el entorno de ejecución almacena en caché en ese método, es específico de la implementación, al igual que la posible presencia de Escape Analysis. En la mayoría de los casos de la vida real, esto no tiene impacto en el rendimiento.Aquí hay una solución, en caso de que no le importe el valor en caso de que sea más grande de lo necesario;)
fuente
too low
? por favor, proporcione el caso de uso.NO: ¡Esto no es una solución!
Mi primer acercamiento fue:
Pero eso simplemente convierte el largo en un int, potencialmente creando nuevas
Long
instancias o recuperándolas del grupo Long.Los inconvenientes
Long.valueOf
crea una nuevaLong
instancia si el número no está dentroLong
del rango del grupo [-128, 127].La
intValue
implementación no hace más que:Por lo tanto, esto puede considerarse incluso peor que simplemente lanzarlo
long
aint
.fuente
Afirmo que la forma obvia de ver si la conversión de un valor cambió el valor sería lanzar y verificar el resultado. Sin embargo, eliminaría el yeso innecesario al comparar. Tampoco me interesan los nombres de variables de una letra (excepción
x
yy
, pero no cuando significan fila y columna (a veces, respectivamente)).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 seguro que la excepción equivocada es lanzar en lo que respecta al código del cliente.fuente
Los tipos enteros de Java se representan con signo. Con una entrada entre 2 31 y 2 32 (o -2 31 y -2 32 ), el lanzamiento tendrá éxito pero su prueba fallará.
Lo que debe verificar es si todos los bits altos de la
long
son todos iguales:fuente
(int) 0xFFFFFFFF
y(long) 0xFFFFFFFFL
tienen valores diferentes, pero ambos contienen la misma "información", y es casi trivial extraer el valor largo original del int.pero Long no puede superar el máximo :)
fuente
+ 0
agrega nada a esta conversión, podría funcionar si Java tratara la concatenación de tipo numérico de una manera similar a las cadenas, pero dado que no hace una operación de agregar sin ninguna razón.Otra solución puede ser:
He intentado esto para los casos en que el cliente está haciendo una POST y el servidor DB solo entiende números enteros mientras el cliente tiene un Long.
fuente
Integer.valueOf(Long.MAX_VALUE.toString());
da como resultadojava.lang.NumberFormatException: For input string: "9223372036854775807"
que ofusca la Excepción fuera de rango porque ahora se trata de la misma manera que se trata una cadena que contiene letras.