Mengapa (i <= j && j <= i && i! = J) bernilai BENAR?


104

Saya telah menulis sepotong kode Java yang berjalan dalam putaran tak terbatas.

Berikut kodenya:

public class TestProgram {
    public static void main(String[] args){
        Integer i = new Integer(0);
        Integer j = new Integer(0);

        while(i<=j && j<=i && i!=j){
            System.out.println(i);
        }
    }
}

Pada kode di atas, saat melihat kondisi dalam whileloop, pada awalnya sepertinya program tersebut tidak akan masuk ke dalam whileloop. Tapi sebenarnya itu adalah loop tak terbatas dan terus mencetak nilainya.

Apa yang terjadi disini?


8
Jawaban sederhana adalah i<=j && j<=i && i!=jkondisi ini selalu bernilai benar. Ambil saja selembar kertas dan evaluasi Anda akan menangkapnya :)
Pradeep Simha

4
Cara Anda membuat integer salah. Gunakan '
bandingkanTo

7
Jika Anda tidak pernah berubah iatau j, kapan Anda mengharapkan loop berakhir?
Fred Larson

33
@PradeepSimha Untuk nilai int sederhana, ini akan selalu menghasilkan false . Dari i<=jdan j<=iAnda dapat menyimpulkan, itu i == j, yang bertentangan dengan istilah terakhir. Dengan demikian seluruh ekspresi bernilai false dan while tidak akan dimasukkan. Poin kuncinya adalah identitas objek di sini!
Sirko

4
Sebagai tambahan, ini adalah teka-teki 32 dalam buku Java Puzzlers: Traps, Pitfalls, and Corner Cases.
Cyanfish

Jawaban:


188
  • i <= jdievaluasi menjadi true, karena unboxing otomatis terjadi untuk perbandingan int dan kemudian keduanya idan jmenahan nilai default , 0.

  • j <= idievaluasi truekarena alasan di atas.

  • i != jdievaluasi untuk true, karena kedua idan jyang objek yang berbeda. Dan saat membandingkan objek, tidak perlu membuka kotak otomatis.

Semua kondisi benar, dan Anda tidak berubah idan jberputar, jadi ini berjalan tanpa batas.


10
dapatkah Anda menjelaskan, mengapa! = memeriksa indeks memori objek referensi dan <= memeriksa nilai Integer yang tidak dikotakkan ?? .. mengapa ada perbedaan seperti itu antara operator ini?
Punith Raj

41
Operator @PunithRaj <&> bekerja pada primitif dan bukan pada objek, maka unboxing otomatis terjadi untuk operator ini. Tetapi operator == dan! = Dapat digunakan untuk perbandingan objek juga jadi tidak perlu membuka kotak di sini, maka objek dibandingkan.
Juned Ahsan

14
Ah, bahaya tersembunyi dari tinju / unboxing implisit !!
Hot Licks

3
Stack Overflow seharusnya hanya menambahkan tag baru, "Pembongkaran otomatis adalah kesalahan terbesar yang pernah dibuat di Java". :-). Kecuali untuk penulis buku Java Puzzler. Gunakan untuk menandai pertanyaan seperti ini.
pengguna949300

4
catatan yang Integer.valueOf(0) == Integer.valueOf(0)selalu dievaluasi ke true karena dalam hal ini objek yang sama dikembalikan (lihat IntegerCache grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/… )
Vitalii Fedorenko

40

Karena Anda sedang membandingkan

  • 0 < = 0 (true) // unboxing

  • 0 > = 0 (true) // unboxing

  • reference != secondReference (true)saat Anda membuat objek, bukan perbandingan primitif. Jadi itu mengevaluasi ke while(true) { // Never ending loop }.


2
Ohh! Naga tersembunyi dari UNBOXING otomatis ... Penjelasan Bagus.
HybrisHelp

17

Objek integer berbeda. Ini berbeda dari tipe int dasar.

Lihat jawaban ini: Bagaimana membandingkan dua Integer dengan benar di Java?

Bagian i != jitu benar, yang Anda harapkan salah.


Meskipun benar, tidak masalah di sini juga tidak menjawab pertanyaan.
Kon

6
@Kon: Sebenarnya inilah jawabannya. Kondisi # 1 dan # 2 dievaluasi truekarena autoboxing. Jika autoboxing # 3 tidak berlaku dan perbandingan terjadi pada level objek (lokasi memori).
Rumah

1

Perulangan tidak berakhir karena kondisi Anda benar (i! = J adalah benar karena ada 2 objek yang berbeda, gunakan Integer.valueOf sebagai gantinya) dan di dalam perulangan nilainya tidak berubah sehingga kondisi Anda tetap benar selamanya.


1

Objek integer berbeda. Ini berbeda dari tipe int dasar. jadi kamu bisa melakukan seperti itu. yang anda lakukan itu hanya membandingkan objeknya dan tentunya hasilnya benar.


1

Ada dua kasus berbeda yang harus kita pahami terlebih dahulu,

kasus 1:

        Integer i = new Integer(10);
        Integer j = new Integer(10);

        System.out.println((i<=j && j<=i && i!=j));
        System.out.println(i!=j);

kasus 2:

        Integer i = 10;
        Integer j = 10;

        System.out.println((i<=j && j<=i && i==j));
        System.out.println(i==j);

keduanya berbeda, sebagai

dalam kasus 1: i!=jakan menjadi truekarena keduanya merujuk ke dua objek yang berbeda di heap dan tidak boleh sama. Tapi

dalam kasus 2: i==jakan menjadi truekarena 10 adalah literal integer dan pemeliharaan Java pool for Integer literalsyang memiliki nilai (-128 <= X <= 127). Jadi, dalam hal ini 10 <= 127 menghasilkan true, Jadi keduanya akan memiliki referensi ke objek yang sama.


0

Mungkin alasannya adalah bahwa 'i' dan 'j' adalah objek, dan perbandingan objek tidak sama dengan perbandingan referensi objek. Harap pertimbangkan untuk menggunakan! I.equals (j) daripada i! = J


0

Program terus menampilkan nilai yang sama ikarena Anda tidak menambah atau mengurangi nilai iatau j. Kondisi di untuk selalu mengevaluasi ke true, jadi ini adalah pengulangan tanpa batas.


Saya pikir pertanyaannya lebih tentang i!=jbagian yang secara mengejutkan mengevaluasi benar dan bukan <=perbandingannya.
Soravux

0

Integer a = new Integer (0); Integer b = new Integer (0);

Perbandingan <= dan> = akan menggunakan nilai tanpa kotak 0, sedangkan! = Akan membandingkan referensi dan akan berhasil karena keduanya adalah objek yang berbeda.

Bahkan ini juga akan berhasil i, e

Bilangan bulat a = 1000; Bilangan bulat b = 1000;

tapi ini tidak:

Integer a = 100; Integer b = 100;

Alasannya adalah karena Integer secara internal menggunakan caching untuk objek Integer antara -128 dan 127 dan mengembalikan instance dari cache tersebut untuk rentang yang dicakupnya. Saya tidak yakin tetapi saya rasa Anda juga dapat mengubah nilai maksimumnya dalam paket "java.lang.Integer.IntegerCache.high".

Untuk pemahaman yang lebih baik, periksa url: https://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching


-3

Anda harus tahu ada sedikit perbedaan di && ini dan ini & saat Anda menggunakan && lalu ketika kondisi pertama benar maka periksa kondisi kedua jika salah maka tidak diperiksa kondisi ketiga karena di & operator jika satu kondisi salah semua pernyataan salah jika digunakan || kemudian jika terlihat benar maka itu mengembalikan benar pada kode Anda karena i dan j sama dengan kondisi pertama dan kedua benar maka pada kondisi ketiga akan menjadi salah karena sama dan kondisi salah.


saya tidak tahu mengapa jawaban saya mendapatkan nilai tambang karena jawaban saya benar lihat tautan ini benar maka sebelum mendapatkan tambang ke jawaban saya baca lebih lanjut stackoverflow.com/questions/5564410/difference-between-and
sara Sodagari
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.