Quelle est la manière la plus idiomatique en Java pour vérifier qu'une distribution de long
à int
ne perd aucune information?
Voici ma mise en œuvre actuelle:
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;
}
Réponses:
Pour cela, une nouvelle méthode a été ajoutée avec Java 8 .
Va jeter un
ArithmeticException
en cas de débordement.Voir:
Math.toIntExact(long)
Plusieurs autres méthodes de sécurité anti-débordement ont été ajoutées à Java 8. Elles se terminent par exact .
Exemples:
Math.incrementExact(long)
Math.subtractExact(long, long)
Math.decrementExact(long)
Math.negateExact(long),
Math.subtractExact(int, int)
la source
addExact
etmultiplyExact
. Il convient de noter que la division (MIN_VALUE/-1
) et la valeur absolue (abs(MIN_VALUE)
) n'ont pas de méthodes de commodité sûres.Math.toIntExact()
au lieu de la distribution habituelleint
? La mise en œuvre deMath.toIntExact()
juste transtypeslong
àint
.Je pense que je le ferais aussi simplement que:
Je pense que cela exprime l'intention plus clairement que le casting répété ... mais c'est quelque peu subjectif.
Note d'intérêt potentiel - en C # ce serait juste:
la source
(!(Integer.MIN_VALUE <= l && l <= Integer.MAX_VALUE))
. J'ai du mal à trouver d'autres façons de le faire. Dommage que Java n'en ait pasunless
.int
.Avec la classe Ints de Google Guava , votre méthode peut être modifiée en:
À partir des documents liés:
Soit
safeLongToInt
dit en passant , vous n'avez pas besoin de l' encapsuleur, sauf si vous voulez le laisser en place pour modifier la fonctionnalité sans refactorisation approfondie bien sûr.la source
Ints.checkedCast
fait exactement ce que fait OP, d'ailleursInts.checkedCast(l)
directement.Ints.saturatedCast
qui renverra la valeur la plus proche au lieu de lever une exception.Avec BigDecimal:
la source
BigDecimal.valueOf(aLong)
, au lieu denew BigDecimal(aLong)
, pour indiquer qu'une nouvelle instance n'est pas requise. La mise en cache de l'environnement d'exécution sur cette méthode est spécifique à l'implémentation, tout comme la présence possible d'Escape Analysis. Dans la plupart des cas réels, cela n'a aucun impact sur les performances.voici une solution, au cas où vous ne vous souciez pas de la valeur au cas où elle serait plus grande que nécessaire;)
la source
too low
? veuillez fournir un cas d'utilisation.DONT: Ce n'est pas une solution!
Ma première approche a été:
Mais cela ne fait que convertir le long en un entier, créant potentiellement de nouvelles
Long
instances ou les récupérant du pool Long.Les inconvénients
Long.valueOf
crée une nouvelleLong
instance si le nombre ne se trouve pas dansLong
la plage du pool de [-128, 127].L'
intValue
implémentation ne fait rien de plus que:Cela peut donc être considéré comme pire que de simplement lancer le
long
toint
.la source
Je prétends que la façon évidente de voir si la conversion d'une valeur a changé la valeur serait de convertir et de vérifier le résultat. Je voudrais cependant supprimer le casting inutile lors de la comparaison. Je ne suis pas non plus trop intéressé par les noms de variables à une lettre (exception
x
ety
, mais pas quand ils signifient ligne et colonne (parfois respectivement)).Cependant, je voudrais vraiment éviter cette conversion si possible. Évidemment, ce n'est parfois pas possible, mais dans ces cas,
IllegalArgumentException
c'est presque certainement la mauvaise exception à lancer en ce qui concerne le code client.la source
Les types d'entiers Java sont représentés comme signés. Avec une entrée entre 2 31 et 2 32 (ou -2 31 et -2 32 ), le lancer réussirait mais votre test échouerait.
Ce qu'il faut vérifier est de savoir si tous les bits hauts du
long
sont tous les mêmes:la source
(int) 0xFFFFFFFF
et(long) 0xFFFFFFFFL
ont des valeurs différentes, mais elles contiennent toutes les deux les mêmes "informations", et il est presque trivial d'extraire la valeur longue d'origine de l'int.mais Long ne peut pas dépasser le maximum :)
la source
+ 0
n'ajoute rien à cette conversion, cela pourrait fonctionner si Java traitait la concaténation de type numérique de la même manière que les chaînes, mais comme il ne vous permet pas d'effectuer une opération d'ajout sans raison.Une autre solution peut être:
J'ai essayé ceci pour les cas où le client fait un POST et la base de données du serveur ne comprend que les entiers alors que le client a un Long.
la source
Integer.valueOf(Long.MAX_VALUE.toString());
entraîne àjava.lang.NumberFormatException: For input string: "9223372036854775807"
peu près l'obscurcissement de l'exception hors plage car elle est désormais traitée de la même manière qu'une chaîne contenant des lettres est traitée.