Membandingkan nilai panjang kotak 127 dan 128

111

Saya ingin membandingkan dua nilai benda panjang menggunakan ifkondisi. Jika nilai ini kurang dari 128 , ifkondisi berfungsi dengan baik, tetapi jika lebih besar dari atau sama dengan 128 , perbandingan gagal.

Contoh:

Long num1 = 127;
Long num2 = 127;

if (num1 == num2) {
    // Works ok
}

Perbandingan pada kode di atas berfungsi dengan baik, tetapi gagal pada kode di bawah ini:

Long num1 = 128;
Long num2 = 128;

if (num1 == num2) {
    // Does NOT work
}

Mengapa ada masalah dalam membandingkan variabel panjang dengan nilai yang lebih besar dari 127 ? Jika tipe data variabel diubah menjadi primitif panjang , maka perbandingan berfungsi untuk semua kasus.

Viraj Dhamal
sumber

Jawaban:

212

TL; DR

Java meng-cache kotak instance Integer dari -128ke 127. Karena Anda menggunakan ==untuk membandingkan referensi objek dan bukan nilai , hanya objek cache yang akan cocok. Bekerja dengan longnilai primitif tanpa kotak atau gunakan .equals()untuk membandingkan Longobjek Anda .

Versi panjang (permainan kata-kata)

Mengapa ada masalah dalam membandingkan variabel panjang dengan nilai lebih dari 127? Jika tipe data dari variabel di atas adalah primitif (panjang) maka kode berfungsi untuk semua nilai.

Java menyimpan cache instance objek Integer dari kisaran -128 hingga 127 . Yang mengatakan:

  • Jika Anda menyetel ke N variabel panjang nilai 127( cache ), instance objek yang sama akan ditunjukkan oleh semua referensi. (N variabel, 1 contoh)
  • Jika Anda menyetel ke N variabel panjang nilainya 128( tidak di-cache ), Anda akan memiliki instance objek yang ditunjukkan oleh setiap referensi. (N variabel, N contoh)

Itulah mengapa ini:

Long val1 = 127L;
Long val2 = 127L;

System.out.println(val1 == val2);

Long val3 = 128L;
Long val4 = 128L;

System.out.println(val3 == val4);

Keluaran ini:

benar
salah

Untuk nilai 127L , karena kedua referensi (val1 dan val2) menunjuk ke instance objek yang sama dalam memori (cache), ia mengembalikan true.

Di sisi lain, untuk nilai 128 , karena tidak ada contoh untuk itu yang di-cache dalam memori, yang baru dibuat untuk setiap tugas baru untuk nilai kotak, menghasilkan dua contoh yang berbeda (ditunjukkan oleh val3 dan val4) dan kembali falsepada perbandingan di antara mereka.

Itu terjadi semata-mata karena Anda membandingkan dua Long referensi objek , bukan longnilai primitif, dengan ==operator. Jika bukan karena mekanisme Cache ini, perbandingan ini akan selalu gagal, jadi masalah sebenarnya di sini adalah membandingkan nilai kotak dengan ==operator.

Mengubah variabel ini menjadi longtipe primitif akan mencegah hal ini terjadi, tetapi jika Anda perlu menyimpan kode Anda menggunakan Longobjek, Anda dapat membuat perbandingan ini dengan aman dengan pendekatan berikut:

System.out.println(val3.equals(val4));                     // true
System.out.println(val3.longValue() == val4.longValue());  // true
System.out.println((long)val3 == (long)val4);              // true

(Diperlukan pemeriksaan nol yang tepat, bahkan untuk coran)

IMO , itu selalu merupakan ide yang baik untuk tetap menggunakan metode .equals () saat berurusan dengan perbandingan Objek.

Tautan referensi:

everton
sumber
15

Java menyimpan nilai primitif dari -128 hingga 127 . Ketika kita membandingkan dua objek Long java secara internal ketik cast ke nilai primitif dan membandingkannya. Tetapi di atas 127 Long object tidak akan mendapatkan tipe kasta. Java menyimpan keluaran dengan metode .valueOf () .

Caching ini berfungsi untuk Byte, Short, Long dari -128 hingga 127. Untuk caching Integer bekerja Dari -128 ke java.lang.Integer.IntegerCache.high atau 127, mana saja yang lebih besar. (Kita dapat menetapkan nilai level teratas hingga nilai Integer mana harus di-cache dengan menggunakan java.lang.Integer.IntegerCache.high).

 For example:
    If we set java.lang.Integer.IntegerCache.high=500;
    then values from -128 to 500 will get cached and 

    Integer a=498;
    Integer b=499;
    System.out.println(a==b)

    Output will be "true".

Objek Float dan Double tidak pernah disimpan dalam cache.

Karakter akan mendapatkan cache dari 0 hingga 127

Anda membandingkan dua objek. jadi == operator akan memeriksa kesetaraan referensi objek. Ada cara berikut untuk melakukannya.

1) ketik cast kedua objek menjadi nilai primitif dan bandingkan

    (long)val3 == (long)val4

2) membaca nilai objek dan membandingkan

    val3.longValue() == val4.longValue()

3) Gunakan metode equals () pada perbandingan objek.

    val3.equals(val4);  
Jay
sumber
14

num1dan num2merupakan benda panjang. Anda harus menggunakan equals()untuk membandingkannya. ==perbandingan mungkin bekerja kadang-kadang karena cara kotak JVM primitif, tetapi tidak bergantung padanya.

if (num1.equals(num1))
{
 //code
}
Nishan
sumber
1
Ini (yang lebih baik), atau bandingkan nilai kembalian .longValue().
Giulio Franco
4

Membandingkan non-primitif (alias Objek) di Java dengan ==membandingkan referensi mereka, bukan nilainya. Longadalah kelas dan dengan demikian Longnilai adalah Objek.

Masalahnya adalah Java Developers ingin orang menggunakan Longseperti dulu longuntuk menyediakan kompatibilitas, yang mengarah pada konsep autoboxing, yang pada dasarnya adalah fitur, yang long-values ​​akan diubah menjadi Long-Objects dan sebaliknya sesuai kebutuhan. Perilaku autoboxing tidak selalu dapat diprediksi, karena tidak ditentukan sepenuhnya.

Jadi agar aman dan memiliki hasil yang dapat diprediksi selalu gunakan .equals()untuk membandingkan objek dan jangan mengandalkan autoboxing dalam hal ini:

Long num1 = 127, num2 = 127;
if(num1.equals(num2)) { iWillBeExecutedAlways(); }
LionC
sumber