Was ist die idiomatischste Methode in Java, um zu überprüfen, ob eine Besetzung von long
bis int
keine Informationen verliert?
Dies ist meine aktuelle Implementierung:
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;
}
Antworten:
Mit Java 8 wurde eine neue Methode hinzugefügt , um genau das zu tun.
Wirft einen
ArithmeticException
im Falle eines Überlaufs.Sehen:
Math.toIntExact(long)
Java 8 wurden mehrere andere überlaufsichere Methoden hinzugefügt. Sie enden mit genau .
Beispiele:
Math.incrementExact(long)
Math.subtractExact(long, long)
Math.decrementExact(long)
Math.negateExact(long),
Math.subtractExact(int, int)
quelle
addExact
undmultiplyExact
. Bemerkenswert ist, dass Division (MIN_VALUE/-1
) und Absolutwert (abs(MIN_VALUE)
) keine sicheren Bequemlichkeitsmethoden haben.Math.toIntExact()
anstelle der üblichen Besetzungint
? Die Umsetzung vonMath.toIntExact()
nur Castslong
zuint
.Ich denke, ich würde es so einfach machen wie:
Ich denke, das drückt die Absicht klarer aus als das wiederholte Casting ... aber es ist etwas subjektiv.
Hinweis von potenziellem Interesse - in C # wäre es nur:
quelle
(!(Integer.MIN_VALUE <= l && l <= Integer.MAX_VALUE))
. Es fällt mir schwer, mich mit anderen Methoden auseinanderzusetzen. Schade, dass Java nicht hatunless
.int
.Mit der Ints- Klasse von Google Guava kann Ihre Methode geändert werden in:
Aus den verknüpften Dokumenten:
Das brauchst du übrigens nicht
safeLongToInt
Wrapper nicht, es sei denn, Sie möchten ihn an Ort und Stelle lassen, um die Funktionalität ohne umfangreiches Refactoring zu ändern.quelle
Ints.checkedCast
macht übrigens genau das, was OP machtInts.checkedCast(l)
direkt auf.Ints.saturatedCast
Wert, der den nächsten Wert zurückgibt, anstatt eine Ausnahme auszulösen.Mit BigDecimal:
quelle
BigDecimal.valueOf(aLong)
, anstatt anzuzeigen,new BigDecimal(aLong)
dass keine neue Instanz erforderlich ist. Ob die Ausführungsumgebung bei dieser Methode zwischengespeichert wird, ist implementierungsspezifisch, genau wie das mögliche Vorhandensein von Escape Analysis. In den meisten Fällen im wirklichen Leben hat dies keinen Einfluss auf die Leistung.Hier ist eine Lösung, falls Sie sich nicht für den Wert interessieren, falls er größer ist als benötigt;)
quelle
too low
? Bitte geben Sie den Anwendungsfall an.NICHT: Dies ist keine Lösung!
Mein erster Ansatz war:
Damit wird jedoch nur das Long in ein Int umgewandelt, wodurch möglicherweise neue
Long
Instanzen erstellt oder aus dem Long-Pool abgerufen werden.Die Nachteile
Long.valueOf
Erstellt eine neueLong
Instanz, wenn die Nummer nicht imLong
Poolbereich liegt [-128, 127].Die
intValue
Implementierung macht nichts weiter als:Das kann also noch schlimmer sein, als nur das
long
zu werfenint
.quelle
Ich behaupte, dass der offensichtliche Weg, um zu sehen, ob das Wirken eines Wertes den Wert verändert hat, darin besteht, das Ergebnis zu wirken und zu überprüfen. Ich würde jedoch die unnötige Besetzung beim Vergleich entfernen. Ich bin auch nicht besonders an Ein-Buchstaben-Variablennamen interessiert (Ausnahme
x
undy
, aber nicht, wenn sie Zeile und Spalte bedeuten (manchmal jeweils)).Eigentlich möchte ich diese Konvertierung aber möglichst vermeiden. Natürlich ist es manchmal nicht möglich, aber in diesen Fällen
IllegalArgumentException
ist es mit ziemlicher Sicherheit die falsche Ausnahme, wenn es um Client-Code geht.quelle
Java-Integer-Typen werden als signiert dargestellt. Mit einem Eingang zwischen 2 31 und 2 32 (oder -2 31 und -2 32 ) wäre die Besetzung erfolgreich, aber Ihr Test würde fehlschlagen.
Es ist zu prüfen, ob alle hohen Bits von
long
gleich sind:quelle
(int) 0xFFFFFFFF
und(long) 0xFFFFFFFFL
haben unterschiedliche Werte, aber beide enthalten die gleichen "Informationen", und es ist fast trivial, den ursprünglichen langen Wert aus dem int zu extrahieren.aber Long kann das Maximum nicht überschreiten :)
quelle
+ 0
fügt dieser Konvertierung nichts hinzu. Es könnte funktionieren, wenn Java die Verkettung numerischer Typen ähnlich wie Zeichenfolgen behandelt, aber da Sie keine Add-Operation ohne Grund ausführen.Eine andere Lösung kann sein:
Ich habe dies für Fälle versucht, in denen der Client einen POST ausführt und die Server-DB nur Ganzzahlen versteht, während der Client einen Long hat.
quelle
Integer.valueOf(Long.MAX_VALUE.toString());
führt dazu,java.lang.NumberFormatException: For input string: "9223372036854775807"
dass die Out-of-Range-Ausnahme so gut wie verschleiert wird, da sie jetzt genauso behandelt wird wie eine Zeichenfolge, die Buchstaben enthält.