Jaki jest najbardziej idiomatyczny sposób w Javie, aby zweryfikować, czy rzutowanie z long
na int
nie traci żadnych informacji?
To jest moja obecna implementacja:
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;
}
Odpowiedzi:
W tym celu dodano nową metodę do Java 8 .
Rzuci
ArithmeticException
w przypadku przepełnienia.Widzieć:
Math.toIntExact(long)
Kilka innych bezpiecznych metod przelewu zostało dodanych do Java 8. Kończą się dokładnie .
Przykłady:
Math.incrementExact(long)
Math.subtractExact(long, long)
Math.decrementExact(long)
Math.negateExact(long),
Math.subtractExact(int, int)
źródło
addExact
imultiplyExact
. Warto zauważyć, że dzielenie (MIN_VALUE/-1
) i wartość bezwzględna (abs(MIN_VALUE)
) nie mają bezpiecznych metod wygody.Math.toIntExact()
zamiast zwykłej obsadyint
? ImplementacjaMath.toIntExact()
just castujelong
doint
.Myślę, że zrobiłbym to tak prosto jak:
Myślę, że to wyraźniej wyraża intencję niż powtarzające się castowanie ... ale jest to nieco subiektywne.
Uwaga potencjalnego zainteresowania - w języku C # byłoby to po prostu:
źródło
(!(Integer.MIN_VALUE <= l && l <= Integer.MAX_VALUE))
. Trudno mi znaleźć inne sposoby na zrobienie tego. Szkoda Java nie maunless
.int
.Dzięki klasie Ints Google Guava możesz zmienić metodę na:
Z powiązanych dokumentów:
Nawiasem mówiąc, nie potrzebujesz
safeLongToInt
otoki, chyba że chcesz zostawić ją na miejscu w celu zmiany funkcjonalności bez obszernego refaktoryzacji.źródło
Ints.checkedCast
Nawiasem mówiąc, Guava robi dokładnie to, co robi OPInts.checkedCast(l)
bezpośrednio.Ints.saturatedCast
która zwróci najbliższą wartość zamiast zgłaszania wyjątku.Z BigDecimal:
źródło
BigDecimal.valueOf(aLong)
zamiastnew BigDecimal(aLong)
, aby zaznaczyć, że nowa instancja nie jest wymagana. To, czy środowisko wykonawcze buforuje przy użyciu tej metody, zależy od implementacji, podobnie jak ewentualna obecność analizy ucieczki. W większości rzeczywistych przypadków nie ma to wpływu na wydajność.oto rozwiązanie, na wypadek gdybyś nie dbał o wartość, gdyby była większa niż potrzebna;)
źródło
too low
? proszę podać przypadek użycia.DONT: To nie jest rozwiązanie!
Moje pierwsze podejście było:
Ale to tylko rzuca long na int, potencjalnie tworząc nowe
Long
instancje lub odzyskując je z puli Long.Wady
Long.valueOf
tworzy nowąLong
instancję, jeśli liczba nie mieści się wLong
zakresie puli [-128, 127].intValue
Realizacja nie robi nic więcej niż:Można to uznać za jeszcze gorsze niż zwykłe przesłanie
long
doint
.źródło
Twierdzę, że oczywistym sposobem sprawdzenia, czy rzutowanie wartości zmieniło wartość, byłoby rzutowanie i sprawdzenie wyniku. Chciałbym jednak usunąć niepotrzebną obsadę podczas porównywania. Nie przepadam też za nazwami zmiennych o jednej literze (wyjątek
x
iy
, ale nie kiedy oznaczają one wiersz i kolumnę (czasami odpowiednio)).Jednak naprawdę chciałbym uniknąć tej konwersji, jeśli to w ogóle możliwe. Oczywiście czasami nie jest to możliwe, ale w takich przypadkach
IllegalArgumentException
prawie na pewno jest to zły wyjątek, jeśli chodzi o podanie kodu klienta.źródło
Typy całkowite Java są reprezentowane jako podpisane. Przy wartości wejściowej między 2 31 a 2 32 (lub -2 31 i -2 32 ) rzutowanie się powiedzie, ale test się nie powiedzie.
Należy sprawdzić, czy wszystkie wysokie bity
long
są takie same:źródło
(int) 0xFFFFFFFF
i(long) 0xFFFFFFFFL
mają różne wartości, ale oba zawierają te same „informacje”, a wyodrębnienie długiej wartości z wartości int jest prawie banalne.ale Long nie może przekroczyć maksimum :)
źródło
+ 0
Dodaje nic do tego nawrócenia, to może działać, jeśli traktowane numeryczną typu Java konkatenacji w sposób podobny do strun, ale ponieważ nie robisz operację dodawania bez powodu.Innym rozwiązaniem może być:
Próbowałem tego w przypadkach, w których klient wykonuje test POST, a serwer DB rozumie tylko liczby całkowite, podczas gdy klient ma wartość Long.
źródło
Integer.valueOf(Long.MAX_VALUE.toString());
powoduje to,java.lang.NumberFormatException: For input string: "9223372036854775807"
że prawie zaciemnia wyjątek poza zakresem, ponieważ jest on teraz traktowany w taki sam sposób, jak traktowany jest ciąg zawierający litery.