Saat menelusuri kode sumber Guava, saya menemukan potongan kode berikut (bagian dari implementasi hashCode
untuk kelas batin CartesianSet
):
int adjust = size() - 1;
for (int i = 0; i < axes.size(); i++) {
adjust *= 31;
adjust = ~~adjust;
// in GWT, we have to deal with integer overflow carefully
}
int hash = 1;
for (Set<E> axis : axes) {
hash = 31 * hash + (size() / axis.size() * axis.hashCode());
hash = ~~hash;
}
hash += adjust;
return ~~hash;
Kedua adjust
dan hash
yang int
s. Dari apa yang saya ketahui tentang Java, ~
berarti negasi bitwise, jadi adjust = ~~adjust
dan hash = ~~hash
harus membiarkan variabel tidak berubah. Menjalankan tes kecil (dengan pernyataan diaktifkan, tentu saja),
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
assert i == ~~i;
}
mengkonfirmasi ini. Dengan asumsi bahwa para pria jambu biji tahu apa yang mereka lakukan, pasti ada alasan bagi mereka untuk melakukan ini. Pertanyaannya adalah apa?
EDIT Seperti yang ditunjukkan dalam komentar, tes di atas tidak termasuk kasus di mana i
sama dengan Integer.MAX_VALUE
. Karena i <= Integer.MAX_VALUE
selalu benar, kita perlu memeriksa kasing di luar loop untuk mencegahnya berulang selamanya. Namun, garisnya
assert Integer.MAX_VALUE == ~~Integer.MAX_VALUE;
menghasilkan peringatan kompiler "Membandingkan ekspresi identik", yang cukup banyak berhasil.
sumber
Integer.MAX_VALUE
. Berbeda dengan-(-Integer.MIN_VALUE) != Integer.MIN_VALUE
.-Integer.MIN_VALUE
membungkusInteger.MIN_VALUE
, jadi meniadakan itu lagi hanya menghasilkanInteger.MIN_VALUE
lagi.-x = (~x) + 1
.Jawaban:
Di Jawa, tidak ada artinya.
Tetapi komentar itu mengatakan bahwa baris ini khusus untuk GWT, yang merupakan cara untuk mengkompilasi Java ke JavaScript.
Dalam JavaScript, bilangan bulat adalah jenis seperti bilangan ganda yang bertindak sebagai bilangan bulat. Mereka memiliki nilai maksimal 2 ^ 53, misalnya. Tetapi operator bitwise memperlakukan angka seolah-olah mereka 32-bit, yang persis seperti yang Anda inginkan dalam kode ini. Dengan kata lain,
~~hash
katakan "perlakukanhash
sebagai angka 32-bit" dalam JavaScript. Secara khusus, ia membuang semua kecuali 32 bit bagian bawah (karena~
operator bitwise hanya melihat bagian bawah 32 bit), yang identik dengan cara kerja overflow Java.Jika Anda tidak memiliki itu, kode hash objek akan berbeda tergantung pada apakah itu dievaluasi di Jawa-tanah atau di tanah JavaScript (melalui kompilasi GWT).
sumber
|0
atau~~
terdengar seperti itu tidak akan sulit, meskipun saya tidak tahu apa yang akan terjadi pada kinerja (Anda harus menambahkannya di setiap langkah dari setiap ekspresi). Saya tidak tahu apa pertimbangan desainnya. Pertama, ketidakkonsistenan didokumentasikan pada halaman kompatibilitas GWT .hashCode
aneh karena sengaja pengadilan, atau bahkan mengharapkan, meluap terjadi. Satu-satunya tempat Anda dapat mengamati inkonsistensi adalah di mana Java int normal akan meluap, yang bukan masalah yang muncul di sebagian besar kode; hanya relevan dalam kasus aneh yang satu ini.