¿Cuál es la forma más idiomática en Java para verificar que un envío desde longa intno 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
ArithmeticExceptionen 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
addExactymultiplyExact. 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 echalongaint.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
safeLongToIntcontenedor, a menos que desee dejarlo en su lugar para cambiar la funcionalidad sin una refactorización extensa, por supuesto.fuente
Ints.checkedCasthace exactamente lo que hace OP, por ciertoInts.checkedCast(l)directamente.Ints.saturatedCastcuá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
Longinstancias o recuperándolas del grupo Long.Los inconvenientes
Long.valueOfcrea una nuevaLonginstancia si el número no está dentroLongdel rango del grupo [-128, 127].La
intValueimplementación no hace más que:Por lo tanto, esto puede considerarse incluso peor que simplemente lanzarlo
longaint.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
xyy, 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
IllegalArgumentExceptiones 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
longson todos iguales:fuente
(int) 0xFFFFFFFFy(long) 0xFFFFFFFFLtienen 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
+ 0agrega 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.