(İ <= j && j <= i && i! = J) neden DOĞRU olarak değerlendirilir?


104

Sonsuz bir döngüde çalışan bir Java kodu yazdım.

Kod aşağıdadır:

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);
        }
    }
}

Yukarıdaki kodda whiledöngüdeki koşulu görürken, ilk bakışta o program whiledöngü içine girmeyecekmiş gibi görünüyor . Ama aslında sonsuz bir döngüdür ve değeri yazdırmaya devam eder.

Burada ne oluyor?


8
Basit cevap, i<=j && j<=i && i!=jbu koşulun her zaman doğru olarak değerlendirilmesidir. Sadece bir kağıt parçası alın ve yakalayacağınızı değerlendirin :)
Pradeep Simha

4
Tam sayı oluşturma şekliniz yanlış. '
CompareTo

7
Hiç değişmezseniz iveya jdöngünün ne zaman sona ermesini beklersiniz?
Fred Larson

33
@PradeepSimha Basit int değerleri için bu her zaman yanlış verir . Dan i<=jve j<=io, sen sonuca varabiliriz i == jGeçen dönem çelişmektedir. Böylece tüm ifade yanlış olarak değerlendirilir ve süre girilmez. Buradaki kilit nokta, nesne kimliğidir!
Sirko

4
Bir kenara, bu Java Bulmacalar: Tuzaklar, Tuzaklar ve Köşe Vakaları kitabındaki 32 numaralı bulmaca.
Cyanfish

Yanıtlar:


188
  • i <= jolarak değerlendirilir true, çünkü otomatik kutudan çıkarma int karşılaştırmaları için gerçekleşir ve ardından her ikisi de ive jvarsayılan değeri tutar 0,.

  • j <= itrueyukarıdaki nedenden dolayı değerlendirilir .

  • i != jdeğerlendirilir trueçünkü her iki, ive jfarklı nesneleridir. Ve nesneleri karşılaştırırken, otomatik kutudan çıkarmaya gerek yoktur.

Tüm koşullar doğrudur ve siz değişmiyorsunuz ive jdöngü içindesiniz, bu yüzden sonsuza kadar çalışıyor.


10
açıklar mısınız, neden! = referans nesnelerin bellek indeksini kontrol ediyor ve <= kutusuz Tamsayı değerini kontrol ediyor ?? .. neden bu operatörler arasında bu kadar fark var?
Punith Raj

41
@PunithRaj <&> operatörleri nesneler üzerinde değil temel öğeler üzerinde çalışır, dolayısıyla bu operatörler için otomatik kutudan çıkarma işlemi gerçekleşir. Ancak == ve! = Operatörleri nesnelerin karşılaştırılması için de kullanılabilir, bu nedenle burada kutuyu açmaya gerek yoktur, dolayısıyla nesneler karşılaştırılır.
Juned Ahsan

14
Ah, örtük boks / kutudan çıkarmanın gizli tehlikeleri !!
Hot Licks

3
Stack Overflow yeni bir etiket eklemelidir, "Otomatik kutudan çıkarma Java'da şimdiye kadar yapılan en büyük hataydı". :-). Java Puzzler kitaplarının yazarları hariç. Bunun gibi soruları etiketlemek için kullanın.
user949300

4
bunun Integer.valueOf(0) == Integer.valueOf(0)her zaman doğru olarak değerlendirildiğini unutmayın çünkü bu durumda aynı nesne döndürülür (bkz. IntegerCache grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/… )
Vitalii Fedorenko

40

Çünkü karşılaştırıyorsun

  • 0 < = 0 (true) // unboxing

  • 0 > = 0 (true) // unboxing

  • reference != secondReference (true)nesneler yaratırken, ilkel bir karşılaştırma değil. Böylece değerlendirir while(true) { // Never ending loop }.


2
Ohh! gizli Ejderhanın otomatik KUTUSU AÇILMASI ... İyi Açıklama.
HybrisHelp

17

Tamsayı nesneleri farklıdır. Temel int türünden farklıdır.

Şu yanıta bakın: Java'da iki Tamsayıyı doğru şekilde nasıl karşılaştırabilirim?

i != jBölüm yanlış olduğu bekliyorduk ki, doğrudur.


Doğru olsa da, burada önemi yok ve soruyu cevaplamıyor.
Kon

6
@Kon: Aslında cevap bu. 1 ve 2 truenumaralı koşullar, otomatik kutulama nedeniyle olarak değerlendirilir . # 3 durumunda otomatik kutulama uygulanmaz ve karşılaştırma nesne (bellek konumu) seviyesinde gerçekleşir.
ev

1

Döngü sona ermiyor çünkü koşulunuz doğru (i! = J doğrudur, çünkü 2 farklı nesne vardır, bunun yerine Integer.valueOf kullanın) ve döngünün içinde değerler değişmediğinden koşulunuz sonsuza kadar doğru kalır.


1

Tamsayı nesneleri farklıdır. Temel int türünden farklıdır. böylece bunu yapabilirsin. Yaptığınız şey sadece nesneyi karşılaştırır ve tabii ki sonuç doğrudur.


1

Önce anlamamız gereken iki farklı durum var.

dava 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);

durum 2:

        Integer i = 10;
        Integer j = 10;

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

ikisi de farklı, çünkü

durumda 1: i!=jolacaktır trueçünkü her ikisi de öbek içindeki iki farklı nesneye başvurur ve aynı olamaz. Fakat

durumda 2: i==jolacaktır, trueçünkü her ikisi de 10 tamsayı değişmezdir ve Java pool for Integer literalsdeğeri olanları korur (-128 <= X <= 127). Dolayısıyla, bu durumda 10 <= 127 sonuç doğru, yani her ikisinin de aynı nesneye başvurusu olacaktır.


0

Belki de nedeni, hem "i" hem de "j" nin nesne olması ve nesne karşılaştırmasının nesne referans karşılaştırması ile aynı şey olmamasıdır. Lütfen i! = J yerine! İ.equals (j) kullanmayı düşünün


0

Program aynı değere görüntülendiği devam ediyor iEğer arttırılması veya azaltma ya değeri olmadığından iya j. For'daki koşul her zaman doğru olarak değerlendirmeye devam eder, bu nedenle sonsuz bir döngüdür.


Bence soru, karşılaştırmalar i!=jyerine şaşırtıcı bir şekilde doğru olarak değerlendirilen kısımla ilgiliydi <=.
Soravux

0

Tamsayı a = yeni Tamsayı (0); Tamsayı b = yeni Tamsayı (0);

<= Ve> = karşılaştırmaları kutulu olmayan 0 değerini kullanırken! = Referansları karşılaştıracak ve farklı nesneler olduklarından başarılı olacaktır.

Bu bile işe yarayacak i, e

Tamsayı a = 1000; Tamsayı b = 1000;

ama bu değil:

Tamsayı a = 100; Tamsayı b = 100;

Bunun nedeni, Tamsayı'nın -128 ile 127 arasındaki Tamsayı nesneleri için dahili olarak önbelleğe almayı kullanması ve kapsadığı aralık için bu önbellekten örnekleri döndürmesidir. Emin değilim ama sanırım maksimum değerini "java.lang.Integer.IntegerCache.high" paketinde de değiştirebilirsiniz.

Daha iyi anlamak için url'yi kontrol edin: https://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching


-3

&& bunun içinde biraz farklı olduğunu bilmelisiniz ve bu & && kullandığınızda, o zaman ilk koşul doğruysa ikinci koşulu kontrol eder, sonra üçüncü koşulu kontrol etmez çünkü & operatörü bir koşul yanlışsa tüm eğer kullanılırsa ifade yanlıştır || o zaman eğer doğru görürse, kodunuzda doğru olarak döner çünkü i ve j birinci ve ikinci koşul doğrudur ve üçüncü durumda yanlış olacaktır çünkü bunlar eşittir ve koşul yanlıştır.


Cevabımın neden maden değeri kazandığını bilmiyorum çünkü cevabım doğru bu bağlantıyı görün,
cevabıma
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.