Java mantıksal işleç kısa devre


100

Hangi küme kısa devre yapıyor ve karmaşık koşullu ifadenin kısa devre olması tam olarak ne anlama geliyor?

public static void main(String[] args) {
  int x, y, z;

  x = 10;
  y = 20;
  z = 30;

  // T T
  // T F
  // F T
  // F F

  //SET A
  boolean a = (x < z) && (x == x);
  boolean b = (x < z) && (x == z);
  boolean c = (x == z) && (x < z);
  boolean d = (x == z) && (x > z);
  //SET B    
  boolean aa = (x < z) & (x == x);
  boolean bb = (x < z) & (x == z);
  boolean cc = (x == z) & (x < z);
  boolean dd = (x == z) & (x > z);

}

Yanıtlar:


244

&&Ve ||gerekli değilse anlamı operatörleri "kısa devre", onlar sağ tarafını değerlendirmek gerekmez.

&Ve |mantıksal operatör olarak kullanıldığında operatör, her zaman için her iki tarafı da değerlendirir.

Her operatör için yalnızca bir kısa devre durumu vardır ve bunlar:

  • false && ...- sağ tarafın ne olduğunu bilmek gerekli değildir çünkü sonuç sadece falseoradaki değerden bağımsız olabilir
  • true || ...- sağ tarafın ne olduğunu bilmek gerekli değildir çünkü sonuç sadece trueoradaki değerden bağımsız olabilir

Davranışı basit bir örnekle karşılaştıralım:

public boolean longerThan(String input, int length) {
    return input != null && input.length() > length;
}

public boolean longerThan(String input, int length) {
    return input != null & input.length() > length;
}

2 versiyonu olmayan kısa devre operatörünü kullanır &ve bir atacağım NullPointerExceptioneğer inputolduğunu null, ancak 1 versiyonu dönecektir falsebir istisnasız.


9
Bu cevabı biraz genişletmek istiyorum. & = Operatörü, x = x & ifadesinin kısaltmasıdır ve bu nedenle kısa devre DEĞİLDİR. Aynı şey | = operatörü için de geçerlidir.
Stormcloud

11
Vurgulamak istediğim bir şey, | ve & ikili operatörler, while && ve || koşullu (mantıksal) operatörlerdir. | ve & booleanlardan daha fazlası üzerinde çalışın, while && ve || yalnızca boolelerde çalışın.
bir efsane

1
Sadece sağ taraftaki ifadeyi değerlendirmezler, değerlendirilecek herhangi bir şey olması için kod çalıştırılmaz. Aksi takdirde bir yan etki üretilip üretilmeyecekse bu kritik bir anlayış noktasıdır.
mckenzm

@mckenzm Değerlendirilen ve yürütülen arasındaki fark nedir?
Kronen

@Kronen Yürütme, değerlendirmeden daha fazlasına neden olabilir ve bir istisna veya gecikme gibi bir yan etki yaratabilir, bu örnekle ilgisi olmayan bir ödeme yapacağım.
mckenzm

9

SET A, kısa devre yapan boole operatörlerini kullanır.

Boole operatörleri bağlamında "kısa devre" nin anlamı, bir boole kümesi b1, b2, ..., bn için, kısa devre versiyonlarının, bu booleanlardan ilki doğru olduğu anda değerlendirmeyi durduracağıdır (|| ) veya yanlış (&&).

Örneğin:

// 2 == 2 will never get evaluated because it is already clear from evaluating
// 1 != 1 that the result will be false.
(1 != 1) && (2 == 2)

// 2 != 2 will never get evaluated because it is already clear from evaluating
// 1 == 1 that the result will be true.
(1 == 1) || (2 != 2)

Lütfen bunun için geçerli olduğunu &&, ||farklı çalıştığını ve true döndüren ilk işlenen üzerinde değerlendirmeyi durduracağını belirtin ;)
fge

1
Aslında, tüm gerçekten tam olduğu &&, ||, &ve |soldan sağa değerlendirir. Bir boole kümesi b1, b2, ..., bn için, kısa devre sürümleri, bu booleanlardan ilki doğru ( ||) veya yanlış ( &&) olduğunda değerlendirmeyi durduracaktır . Bah, prensip orada;)
fge

@fge: Evet, tabii haklısın. Senin tanımın benimkinden daha mükemmel. Cevabımı yorumunuzdaki cümle ile güncelledim. Umarım aldırmazsın
afrischke

Endişeye gerek yok, bilginin paylaşılmadığı takdirde değeri yoktur.
FGE

4

Kısa devre, birinci operatör nihai sonuca karar verirse ikinci operatörün kontrol edilmeyeceği anlamına gelir.

Örneğin İfade: Doğru || Yanlış

|| durumunda, ihtiyacımız olan tek şey True olacak taraflardan biridir . Yani sol taraf doğruysa, sağ tarafı kontrol etmenin bir anlamı yoktur ve dolayısıyla bu hiç kontrol edilmeyecektir.

Benzer şekilde, Yanlış && Doğru

&& durumunda, her iki tarafın da Doğru olmasına ihtiyacımız var . Dolayısıyla, sol taraf Yanlış ise, sağ tarafı kontrol etmenin bir anlamı yoktur, yanıt Yanlış olmalıdır. Ve dolayısıyla bu hiç kontrol edilmeyecek.


4
boolean a = (x < z) && (x == x);

Bu tür kısa devre yapar, yani (x < z)yanlış olarak değerlendirilirse ikincisi değerlendirilmez a, aksi takdirde yanlış olur&& takdirde de değerlendirilir (x == x).

& bitsel bir operatördür, fakat aynı zamanda kısa devre yapmayan bir mantıksal VE operatörüdür.

Bunları aşağıdaki gibi bir şeyle test edebilirsiniz (her durumda yöntemin kaç kez çağrıldığını görün):

public static boolean getFalse() {
    System.out.println("Method");
    return false;
}

public static void main(String[] args) {
    if(getFalse() && getFalse()) { }        
    System.out.println("=============================");        
    if(getFalse() & getFalse()) { }
}

-1 Yanıtınız düşündürmektedir &olan sadece bir bit düzeyinde operatörü, ama bu doğru değildir. Aynı zamanda bir boolean "veya" operatörüdür.
Bohemian

@Bohemian: Uyarılar için teşekkürler. true & falseyanlış olarak değerlendirilir. Lütfen bu "boole" veya "operatörü" açıklayabilir misiniz? Belki de söylemeye çalıştığınız şeyi anlamıyorum.
Bhesh Gurung

Üzgünüm - Boole'yi kastetmiştim AND, değil OR! ie true & falsegeçerli bir sözdizimidir. -1 kaldırıldı :)
Bohemian

4

Açıkça ifade etmek gerekirse , kısa devre , cevabın artık değişemeyeceğini bildiğinizde değerlendirmeyi durdurmak anlamına gelir. Örneğin, bir mantıksal ANDs zincirini değerlendiriyorsanız ve FALSEbu zincirin ortasında bir keşfederseniz , zincirdeki geri kalan ifadelerin değerleri ne olursa olsun sonucun yanlış olacağını bilirsiniz. Aynı şey bir ORs zinciri için de geçerlidir : a'yı keşfettiğinizde TRUE, cevabı hemen bilirsiniz ve böylece geri kalan ifadeleri değerlendirmeyi atlayabilirsiniz.

Kısa devre yapmak istediğinizi Java'ya &&yerine &ve ||yerine kullanarak belirtirsiniz |. Gönderinizdeki ilk set kısa devre yapıyor.

Bunun birkaç CPU döngüsünü kaydetme girişiminden daha fazlası olduğunu unutmayın: bunun gibi ifadelerde

if (mystring != null && mystring.indexOf('+') > 0) {
    ...
}

kısa devre, doğru işlem ile bir çarpışma arasındaki fark anlamına gelir (mystring'in boş olduğu durumda).


2

Java, diğer bilgisayar dillerinin çoğunda bulunmayan iki ilginç Boole operatörü sağlar. AND ve OR'nin bu ikincil versiyonları, kısa devre mantıksal operatörler olarak bilinir . Önceki tablodan da görebileceğiniz gibi, OR operatörü, B ne olursa olsun, A doğru olduğunda doğru sonucunu verir.

Benzer şekilde, AND operatörü, B ne olursa olsun, A yanlış olduğunda yanlışla sonuçlanır. Bu operatörlerin ve formları yerine ||ve &&formlarını kullanırsanız , Java sağ taraftaki operandı tek başına değerlendirme zahmetine girmeyecektir. Sağ el operandının düzgün çalışması için soldaki doğru veya yanlış olmasına bağlı olduğunda bu çok kullanışlıdır.|&

Örneğin, aşağıdaki kod parçası, bir bölme işleminin değerlendirmeden önce geçerli olacağından emin olmak için kısa devre mantıksal değerlendirmeden nasıl yararlanabileceğinizi gösterir:

if ( denom != 0 && num / denom >10)

AND ( &&) 'nin kısa devre formu kullanıldığından, sıfıra bölmeden çalışma zamanı istisnasına neden olma riski yoktur. Bu kod satırı, AND'nin tek &sürümü kullanılarak yazıldıysa , her iki tarafın da değerlendirilmesi gerekir ve denomsıfır olduğunda bir çalışma zamanı istisnasına neden olur .

Boole mantığını içeren durumlarda, tek karakterli sürümleri yalnızca bitsel işlemler için bırakarak AND ve OR'nin kısa devre biçimlerini kullanmak standart bir uygulamadır. Ancak bu kuralın istisnaları vardır. Örneğin, aşağıdaki ifadeyi düşünün:

 if ( c==1 & e++ < 100 ) d = 100;

Burada tek kullanmak &, artırma işleminin 1'e eşit eolup olmamasına uygulanmasını sağlar c.


2

Mantıksal VEYA: - işlenenlerden en az biri doğru olarak değerlendirilirse doğru döndürür. OR operatörü uygulanmadan önce her iki işlenen de değerlendirilir.

Kısa Devre VEYA: - sol taraftaki işlenen doğru dönerse, sağ taraftaki işleneni değerlendirmeden doğru döndürür.


2

&Ve &&operatörleri arasında birkaç fark vardır . Aynı farklılıklar |ve için de geçerlidir ||. Akılda tutulması gereken en önemli şey olduğunu &&bir olduğunu mantıksal iken, sadece boolean operandların için geçerlidir operatör &bir olduğunu bitsel tamsayı türlerinin yanı sıra boolelerde için de geçerlidir operatörü.

Mantıksal işlem ile, çünkü bazı durumlarda (ilk işlenen gibi kısa devreyi yapabilirsiniz &&olma falseya ilk işlenen ||olma true), ifadenin geri kalanını değerlendirmek gerekmez. Bu, nullbir dosyaya veya yönteme erişmeden önce kontrol etmek ve bunlara bölmeden önce potansiyel sıfırları kontrol etmek gibi şeyler yapmak için çok kullanışlıdır . Karmaşık bir ifade için, ifadenin her bir parçası aynı şekilde özyinelemeli olarak değerlendirilir. Örneğin, aşağıdaki durumda:

(7 == 8) || ( (1 == 3) && (4 == 4))

Yalnızca vurgulanan kısımlar değerlendirilecektir. Hesaplamak için ||ise, ilk çek 7 == 8olduğunu true. Öyle olsaydı, sağ taraf tamamen atlanırdı. Eğer sağ taraf sadece denetler 1 == 3olduğunu false. O olduğundan, 4 == 4kontrol edilmesi gereken ve tüm anlatım değerlendirir için değilfalse . Eğer sol taraf true, örneğin, 7 == 7yerine, 7 == 8sağ tarafın tamamı atlanacaktır çünkü tüm ||ifade truedikkate alınmayacaktır .

Bitsel bir işlemle, tüm işlenenleri değerlendirmeniz gerekir çünkü gerçekten sadece bitleri birleştiriyorsunuz. Booleanlar, Java'da etkili bir şekilde bir bitlik tam sayıdır (dahililerin nasıl çalıştığına bakılmaksızın) ve bu özel durumda bitsel operatörler için kısa devre yapabilmeniz sadece bir tesadüftür. Genel bir tamsayıyı &veya |işlemi kısa devre yapamamanızın nedeni, her iki işlenende de bazı bitlerin açık ve bazılarının kapalı olabilmesidir. Benzer bir şey 1 & 2sıfır verir, ancak her iki işleneni de değerlendirmeden bunu bilmenin hiçbir yolu yoktur.


1
if(demon!=0&& num/demon>10)

AND (&&) 'nin kısa devre formu kullanıldığından, demon sıfır olduğunda çalışma zamanı istisnasına neden olma riski yoktur.

Ref. Herbert Schildt tarafından hazırlanan Java 2 Beşinci Baskı

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.