&& (AND) ve || (VEYA) IF ifadelerinde


137

Takip koduna sahibim:

if(!partialHits.get(req_nr).containsKey(z) || partialHits.get(req_nr).get(z) < tmpmap.get(z)){  
    partialHits.get(z).put(z, tmpmap.get(z));  
}

partialHitsbir HashMap nerede .
İlk ifade doğruysa ne olacak? Java yine de ikinci ifadeyi kontrol edecek mi? Çünkü ilk ifadenin doğru olması için, HashMap verilen anahtarı içermemelidir, bu yüzden ikinci ifade kontrol edilirse, alacağım NullPointerException.
Basit bir deyişle, eğer aşağıdaki kodumuz varsa

if(a && b)  
if(a || b)

Java ilk durumda yanlış olup olmadığını ve ikinci durumda doğru olup bolmadığını kontrol eder mi?aa

Yanıtlar:


202

Hayır, değerlendirmeye alınmayacak. Ve bu çok faydalı. Örneğin, bir Dizenin boş veya boş olup olmadığını sınamanız gerekiyorsa şunları yazabilirsiniz:

if (str != null && !str.isEmpty()) {
  doSomethingWith(str.charAt(0));
}

ya da başka türlü

if (str == null || str.isEmpty()) {
  complainAboutUnusableString();
} else {
  doSomethingWith(str.charAt(0));
}

Java'da 'kısa devre' olmasaydı, yukarıdaki kod satırlarında çok fazla NullPointerExceptions alırdık.


Her iki ifadeyi de değerlendirebilmeniz için bitsel karşılaştırmalar var mı? ie if (str! = null | str.isEmpty ())? (elbette bu pratik bir örnek değil, aslında aptalca, ama fikri
anlıyorsunuz

5
İfadelerin yan etkileri olmadığı sürece, kısa devre semantiği mantıksal olarak tam değerlendirmeye eşdeğerdir. Yani, A doğruysa, B'yi değerlendirmek zorunda kalmadan A || B'nin doğru olduğunu bilirsiniz. Fark yaratacak tek zaman, bir ifadenin yan etkileri olup olmadığıdır. Diğer operatörler gelince, kullanabileceğiniz *ve +mantıksal olarak andve or; ((A?1:0) * (B?1:0)) == 1, ((A?1:0) + (B?1:0)) > 0. Hatta yapabilirsiniz xor: ((A?1:0) + (B?1:0)) == 1.
outis

1
@Kezzer: Bu gerçekten bitsel bir karşılaştırma mı? Bence boolean(mantıklı) bir operatör. bitwiseAynı simgeye sahip olmasına rağmen , (tamsayı) operatöründen farklı ...
user85421

4
'&&' ve '||' arasında geçiş yapmak istediğinizde kullanışlı bir numara ifadeler, tüm ifadeyi, şu şekilde !(str != null && !str.isEmpty()) olur: (str !(!=) null !(&&) !(!)str.isEmpty()) ve sonra: (str == null || str.isEmpty()) çünkü: !(!=) is == !(&&) is || !(!) eliminates itself diğer yararlı olumsuzlamalar şunlardır: !(<) is >= !(>) is <= ve viceversa
egallardo

68

Java'nın 5 farklı boolean karşılaştırma operatörü vardır: &, &&, |, ||, ^

& ve && "ve" operatörleri, | ve || "veya" operatörleri, ^ "xor"

Tek olanlar, parametrelerin değerlerini kontrol etmeden önce değerlerden bağımsız olarak her parametreyi kontrol edecektir. İkili olanlar önce sol parametreyi ve değerini kontrol edecek ve true( ||) veya false( &&) ikincisine dokunulmamışsa. Ses derlendi mi? Kolay bir örnek bunu açıkça belirtmelidir:

Tüm örnekler için verilmiştir:

 String aString = null;

VE:

 if (aString != null & aString.equals("lala"))

Değerlendirme yapılmadan önce her iki parametre de kontrol edilir ve ikinci parametre için bir NullPointerException oluşturulur.

 if (aString != null && aString.equals("lala"))

İlk parametre kontrol edilir ve geri döner false, böylece sonuç falseyine de olduğu için ikinci parametre kontrol edilmez .

Aynı şey OR için:

 if (aString == null | !aString.equals("lala"))

NullPointerException da yükseltir.

 if (aString == null || !aString.equals("lala"))

İlk parametre kontrol edilir ve geri döner true, böylece sonuç trueyine de olduğu için ikinci parametre kontrol edilmez .

XOR optimize edilemez, çünkü her iki parametreye de bağlıdır.


3
"Java 4 farklı boole karşılaştırma operatörüne sahiptir: &, &&, |, ||" ... ^Unutuyorsunuz (xor).
aioobe

Oh, boole boole değerlerini de kontrol ettiğinin farkında değildim. Şimdiye kadar sadece bit maskeleri için kullandı.
Kodlanmış


20

Buradaki tüm cevaplar harika, ancak bunun nereden geldiğini göstermek için, bunun gibi sorular için kaynağa gitmek iyidir: Java Dil Spesifikasyonu.

Şartlı ve operatör (&&) Bölüm 15:23 , şöyle diyor:

&& operatörü & (§15.22.2) gibidir, ancak sağ işlenenini yalnızca sol işleneninin değeri doğru olduğunda değerlendirir. [...] Çalışma zamanında, önce sol taraftaki işlenen ifade değerlendirilir [...] eğer sonuçtaki değer yanlışsa, koşullu ve ifadenin değeri yanlış olur ve sağ taraftaki işlenen ifade değerlendirilmez . Sol taraftaki işlenenin değeri doğruysa, sağ taraftaki ifade değerlendirilir [...] elde edilen değer koşullu ve ifadenin değeri olur. Böylece, &&, boole işlenenlerinde & ile aynı sonucu hesaplar. Yalnızca sağ taraftaki işlenen ifadesinin her zaman değil koşullu olarak değerlendirilmesi bakımından farklılık gösterir.

Benzer şekilde, Koşullu-Veya operatör (||) , Bölüm 15:24 şöyle der:

|| operatörü gibidir | (§15.22.2) içerir, ancak sağ el işlenenini yalnızca sol el işleneninin değeri yanlışsa değerlendirir. [...] Çalışma zamanında, önce sol taraftaki işlenen ifade değerlendirilir; [...] sonuçta elde edilen değer doğruysa, koşullu veya ifadenin değeri doğrudur ve sağ taraftaki işlenen ifadesi değerlendirilmez. Sol taraftaki işlenenin değeri yanlışsa, sağ taraftaki ifade değerlendirilir; [...] sonuçta ortaya çıkan değer koşullu veya ifadenin değeri olur. Böylece || ile aynı sonucu hesaplar | boolean veya Boolean işlenenlerinde. Yalnızca sağ taraftaki işlenen ifadesinin her zaman değil koşullu olarak değerlendirilmesi bakımından farklılık gösterir.

Biraz tekrarlayan, belki, ama tam olarak nasıl çalıştıklarının en iyi onayı. Benzer şekilde koşullu işleç (? :) yalnızca uygun 'yarısını' (değer doğruysa sol yarıyı, yanlışsa sağ yarıyı) değerlendirerek aşağıdaki ifadelerin kullanılmasına izin verir:

int x = (y == null) ? 0 : y.getFoo();

NullPointerException olmadan.


6

Hayır, eğer a doğruysa (bir ortestte), testin sonucu her zaman doğru olacağından, b ifadesinin değeri ne olursa olsun, b test edilmeyecektir.

Basit bir test yapın:

if (true || ((String) null).equals("foobar")) {
    ...
}

olacak değil bir atmak NullPointerException!


6

Buradaki kısa devre, ikinci koşulun değerlendirilmeyeceği anlamına gelir.

Eğer (A && B), A Yanlışsa kısa devreye neden olur.

(A && B) Eğer değil kısa Circuit neden A True ise.

(A || B) ise A Doğru ise kısa devreye neden olur.

(A || B) ise A Yanlış ise kısa devreye neden olmaz .


4

Hayır, olmaz, Java kısa devre yapar ve sonucu öğrendikten sonra değerlendirmeyi durdurur.


4

Evet, boole ifadeleri için kısa devre değerlendirmesi tüm C benzeri ailede varsayılan davranıştır.

Ilginç bir gerçeği Java da kullanılıyor olmasıdır &ve |mantık işlenenle (onlar ile aşırı yüklü olarak intsize yan etkileri gerektiğinde de yararlıdır ifadesi tüm terimleri değerlendirmek türleri beklediklerinden bitsel operasyonlardır).


Bunu hatırlamak ilginçtir: örneğin bir boole döndüren bir changeData (data) yöntemi verildiğinde: if (a.changeData (data) || b.changeData (data)) {doSomething (); } a.changeData () işlevi true değerini döndürürse b üzerinde changeData öğesini çalıştırmaz, ancak (a.changeData (data) | b.changeData (data)) {doSomething ()}, hem a hem de b üzerinde changeData () öğesini çalıştırırsa bile eğer kişi geri dönen bir doğruya çağırırsa.
Sampisa

0

Bu, & ve &&, | ve ||

BTW Aynı görevleri birçok kez gerçekleştirirsiniz. Verimliliğin bir sorun olup olmadığından emin değilim. Çoğaltmanın bir kısmını kaldırabilirsiniz.

Z z2 = partialHits.get(req_nr).get(z); // assuming a value cannout be null.
Z z3 = tmpmap.get(z); // assuming z3 cannot be null.
if(z2 == null || z2 < z3){   
    partialHits.get(z).put(z, z3);   
} 
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.