Apa cara paling idiomatis di Jawa untuk memverifikasi bahwa para pemain dari long
ke int
tidak kehilangan informasi apa pun?
Ini adalah implementasi saya saat ini:
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;
}
Jawaban:
Metode baru telah ditambahkan dengan Java 8 untuk melakukan hal itu.
Akan melempar
ArithmeticException
jika terjadi luapan.Lihat:
Math.toIntExact(long)
Beberapa metode overflow aman lainnya telah ditambahkan ke Java 8. Mereka berakhir dengan tepat .
Contoh:
Math.incrementExact(long)
Math.subtractExact(long, long)
Math.decrementExact(long)
Math.negateExact(long),
Math.subtractExact(int, int)
sumber
addExact
danmultiplyExact
. Yang perlu diperhatikan adalah pembagian (MIN_VALUE/-1
) dan nilai absolut (abs(MIN_VALUE)
) tidak memiliki metode kenyamanan yang aman.Math.toIntExact()
bukan pemain biasaint
? ImplementasiMath.toIntExact()
hanya dilemparkanlong
keint
.Saya pikir saya akan melakukannya sesederhana:
Saya pikir itu mengekspresikan maksud lebih jelas daripada casting berulang ... tapi itu agak subyektif.
Catatan minat potensial - dalam C # itu hanya akan menjadi:
sumber
(!(Integer.MIN_VALUE <= l && l <= Integer.MAX_VALUE))
. Saya merasa sulit untuk mencari cara lain untuk melakukannya. Kasihan Java tidak punyaunless
.int
.Dengan kelas Inva Google Guava , metode Anda dapat diubah menjadi:
Dari dokumen tertaut:
Kebetulan, Anda tidak memerlukan
safeLongToInt
pembungkus, kecuali Anda ingin membiarkannya di tempat untuk mengubah fungsi tanpa tentu saja refactoring yang luas.sumber
Ints.checkedCast
melakukan persis apa yang OP lakukan, secara kebetulanInts.checkedCast(l)
langsung.Ints.saturatedCast
yang akan mengembalikan nilai terdekat daripada melemparkan pengecualian.Dengan BigDecimal:
sumber
BigDecimal.valueOf(aLong)
, alih-alihnew BigDecimal(aLong)
, untuk menyatakan bahwa instance baru tidak diperlukan. Apakah lingkungan eksekusi tidak caching pada metode itu, apakah implementasi spesifik, seperti halnya kemungkinan adanya Analisis Escape. Dalam kebanyakan kasus kehidupan nyata, ini tidak berdampak pada kinerja.berikut ini solusinya, jika Anda tidak peduli dengan nilai jika itu lebih besar dari yang dibutuhkan;)
sumber
too low
? tolong berikan kasus penggunaan.DONT: Ini bukan solusi!
Pendekatan pertama saya adalah:
Tapi itu hanya sekedar melemparkan long ke int, berpotensi menciptakan
Long
instance baru atau mengambilnya dari Long pool.Kekurangannya
Long.valueOf
membuatLong
contoh baru jika nomor tersebut tidak berada dalamLong
kisaran kumpulan [-128, 127].The
intValue
pelaksanaan tidak apa-apa lebih dari:Jadi ini bisa dianggap lebih buruk daripada hanya melemparkan
long
keint
.sumber
Saya mengklaim bahwa cara yang jelas untuk melihat apakah casting nilai mengubah nilainya adalah dengan melemparkan dan memeriksa hasilnya. Saya akan, bagaimanapun, menghapus pemain yang tidak perlu saat membandingkan. Saya juga tidak terlalu tertarik pada satu nama variabel huruf (pengecualian
x
dany
, tetapi tidak ketika itu berarti baris dan kolom (kadang-kadang masing-masing)).Namun, sungguh saya ingin menghindari konversi ini jika memungkinkan. Jelas kadang-kadang itu tidak mungkin, tetapi dalam kasus-kasus
IllegalArgumentException
itu hampir pasti pengecualian yang salah untuk membuang sejauh kode klien yang bersangkutan.sumber
Jenis integer Java direpresentasikan sebagai ditandatangani. Dengan input antara 2 31 dan 2 32 (atau -2 31 dan -2 32 ) para pemain akan berhasil tetapi tes Anda akan gagal.
Yang perlu diperiksa adalah apakah semua bit tinggi
long
semua sama:sumber
(int) 0xFFFFFFFF
dan(long) 0xFFFFFFFFL
memiliki nilai yang berbeda, tetapi keduanya mengandung "informasi" yang sama, dan hampir sepele untuk mengekstrak nilai panjang asli dari int.tapi Panjang tidak bisa melebihi maksimum :)
sumber
+ 0
menambahkan tidak ada konversi ini, mungkin bekerja jika Java diperlakukan jenis Rangkaian numerik dalam cara yang mirip dengan string, tetapi karena tidak Anda melakukan operasi add tanpa alasan.Satu solusi lain dapat:
Saya telah mencoba ini untuk kasus-kasus di mana klien melakukan POST dan server DB hanya memahami bilangan bulat sementara klien memiliki panjang.
sumber
Integer.valueOf(Long.MAX_VALUE.toString());
hasiljava.lang.NumberFormatException: For input string: "9223372036854775807"
yang cukup banyak mengaburkan Pengecualian Di Luar Jangkauan karena sekarang diperlakukan dengan cara yang sama dengan string yang berisi huruf diperlakukan.