Kurzschluss des logischen Java-Operators


99

Welche Menge ist kurzgeschlossen und was genau bedeutet es, dass der komplexe bedingte Ausdruck kurzschließt?

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

}

Antworten:


243

Die &&und ||Operatoren "schließen kurz", was bedeutet, dass sie die rechte Seite nicht bewerten, wenn dies nicht erforderlich ist.

Die &und |Betreiber, wenn sie als logische Operatoren verwendet, zu bewerten immer beide Seiten.

Es gibt nur einen Fall von Kurzschluss für jeden Bediener, und das sind:

  • false && ...- Es ist nicht erforderlich zu wissen, was die rechte Seite ist, da das Ergebnis nur falseunabhängig vom Wert dort sein kann
  • true || ...- Es ist nicht erforderlich zu wissen, was die rechte Seite ist, da das Ergebnis nur trueunabhängig vom Wert dort sein kann

Vergleichen wir das Verhalten in einem einfachen Beispiel:

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

Die 2. Version verwendet den Nicht-Kurzschluss-Operator &und gibt ein NullPointerExceptionif inputis aus null, die 1. Version gibt jedoch falseausnahmslos zurück.


9
Ich möchte diese Antwort nur ein wenig erweitern. Der Operator & = ist eine Abkürzung für x = x & expression und schließt daher NICHT kurz. Gleiches gilt für den Operator | =.
Stormcloud

11
Eine Sache möchte ich hervorheben, | und & sind binäre Operatoren, während && und || sind bedingte (logische) Operatoren. | und & arbeiten an mehr als nur Booleschen Werten, während && und || Arbeit nur auf Booleschen.
Ein Mythos

1
Sie bewerten nicht nur den Ausdruck auf der rechten Seite nicht, der Code wird auch nicht ausgeführt, damit etwas ausgewertet werden kann. Dies ist ein kritischer Punkt, um zu verstehen, ob sonst eine Nebenwirkung auftreten würde.
McKenzm

@mckenzm Was ist der Unterschied zwischen ausgewertet und ausgeführt?
Kronen

@Kronen Die Ausführung kann zu mehr als der Bewertung führen und einen Nebeneffekt hervorrufen, z. B. eine Ausnahme oder eine Verzögerung. Ich zahle für dieses Beispiel nicht relevant.
McKenzm

9

SET A verwendet kurzschließende boolesche Operatoren.

Was "Kurzschluss" im Zusammenhang mit Booleschen Operatoren bedeutet, ist, dass für eine Menge von Booleschen Werten b1, b2, ..., bn die Kurzschlussversionen die Auswertung einstellen, sobald der erste dieser Booleschen Werte wahr ist (||) ) oder falsch (&&).

Beispielsweise:

// 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)

Bitte geben Sie an, dass dies der Fall ist &&, ||anders funktioniert und die Auswertung des ersten Operanden beendet, der true zurückgibt;)
fge

1
In der Tat, wirklich vollständig zu sein, alle &&, ||, &und |bewerten links nach rechts. Für eine Menge von Booleschen Werten b1, b2, ..., bn werden die Kurzschlussversionen nicht mehr ausgewertet, wenn der erste dieser Booleschen Werte wahr ( ||) oder falsch ( &&) ist. Bah, das Prinzip ist da;)
fge

@fge: Ja, du hast natürlich recht. Ihre Definition ist genauer als meine. Ich habe meine Antwort mit dem Satz in Ihrem Kommentar aktualisiert. Ich hoffe es macht dir nichts aus.
Afrischke

Keine Sorge, Wissen hat keinen Wert, wenn es nicht geteilt wird.
fge

4

Kurzschluss bedeutet, dass der zweite Bediener nicht überprüft wird, wenn der erste Bediener über das Endergebnis entscheidet.

ZB Ausdruck ist: Wahr || Falsch

Im Fall von || brauchen wir nur eine Seite , um wahr zu sein. Wenn also die linke Seite wahr ist, macht es keinen Sinn, die rechte Seite zu überprüfen, und daher wird dies überhaupt nicht überprüft.

Ebenso False && True

Im Fall von && müssen beide Seiten wahr sein. Wenn also die linke Seite falsch ist, macht es keinen Sinn, die rechte Seite zu überprüfen. Die Antwort muss falsch sein. Und daher wird das überhaupt nicht überprüft.


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

Diese Art wird kurzgeschlossen, dh wenn (x < z)sie als falsch ausgewertet wird, awird letztere nicht ausgewertet, ist falsch, andernfalls &&wird auch ausgewertet (x == x).

& ist ein bitweiser Operator, aber auch ein boolescher UND-Operator, der nicht kurzschließt.

Sie können sie folgendermaßen testen (sehen Sie, wie oft die Methode jeweils aufgerufen wird):

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 Ihre Antwort legt nahe , dass &ist nur ein Bit - Operator, aber das ist nicht wahr. Es ist auch ein boolescher "oder" Operator.
Böhmisch

@Bohemian: Danke für das Heads Up. true & falseergibt false. Können Sie bitte diesen "Booleschen" oder "Operator" erklären? Vielleicht verstehe ich nicht, was Sie sagen wollen.
Bhesh Gurung

Entschuldigung - ich meinte boolesch AND, nicht OR! dh true & falseist gültige Syntax. -1 entfernt :)
Bohemian

4

Kurz gesagt bedeutet Kurzschluss , die Auswertung zu beenden , sobald Sie wissen, dass sich die Antwort nicht mehr ändern kann. Wenn Sie beispielsweise eine Kette logischer ANDs auswerten und eine FALSEin der Mitte dieser Kette entdecken , wissen Sie, dass das Ergebnis falsch sein wird, unabhängig von den Werten der übrigen Ausdrücke in der Kette. Gleiches gilt für eine Kette von ORs: Sobald Sie a entdeckt haben TRUE, kennen Sie die Antwort sofort und können die Auswertung der restlichen Ausdrücke überspringen.

Sie geben Java an, dass Sie einen Kurzschluss wünschen, indem Sie &&anstelle von &und ||anstelle von verwenden |. Der erste Satz in Ihrem Beitrag ist ein Kurzschluss.

Beachten Sie, dass dies mehr als ein Versuch ist, einige CPU-Zyklen zu speichern: in solchen Ausdrücken

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

Kurzschluss bedeutet einen Unterschied zwischen korrektem Betrieb und einem Absturz (in dem Fall, in dem mystring null ist).


2

Java bietet zwei interessante Boolesche Operatoren, die in den meisten anderen Computersprachen nicht zu finden sind. Diese sekundären Versionen von UND und ODER werden als logische Kurzschlussoperatoren bezeichnet . Wie Sie aus der vorhergehenden Tabelle sehen können, ergibt der OR-Operator true, wenn A true ist, unabhängig davon, was B ist.

In ähnlicher Weise führt der AND-Operator zu false, wenn A false ist, unabhängig davon, was B ist. Wenn Sie die ||und &&-Formen anstelle der |und &-Formen dieser Operatoren verwenden, wird Java nicht die Mühe machen, den rechten Operanden allein auszuwerten. Dies ist sehr nützlich, wenn der rechte Operand davon abhängt, dass der linke wahr oder falsch ist, um ordnungsgemäß zu funktionieren.

Das folgende Codefragment zeigt beispielsweise, wie Sie die logische Kurzschlussauswertung nutzen können, um sicherzustellen, dass eine Teilungsoperation gültig ist, bevor Sie sie auswerten:

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

Da die Kurzschlussform von AND ( &&) verwendet wird, besteht kein Risiko, dass eine Laufzeitausnahme durch Teilen durch Null verursacht wird. Wenn diese Codezeile mit der einzelnen &Version von AND geschrieben würde, müssten beide Seiten ausgewertet werden, was zu einer Laufzeitausnahme führen würde, wenn denomNull ist.

Es ist üblich, die Kurzschlussformen von UND und ODER in Fällen mit boolescher Logik zu verwenden, wobei die Einzelzeichenversionen ausschließlich für bitweise Operationen übrig bleiben. Es gibt jedoch Ausnahmen von dieser Regel. Betrachten Sie beispielsweise die folgende Aussage:

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

Hier stellt die Verwendung einer einzelnen &Option sicher, dass die Inkrementierungsoperation angewendet wird, eunabhängig davon, ob sie cgleich 1 ist oder nicht.


2

Logisches ODER: - gibt true zurück, wenn mindestens einer der Operanden true ergibt. Beide Operanden werden ausgewertet, bevor der OR-Operator angewendet wird.

Kurzschluss ODER: - Wenn der linke Operand true zurückgibt, gibt er true zurück, ohne den rechten Operanden auszuwerten.


2

Es gibt einige Unterschiede zwischen den Operatoren &und &&. Die gleichen Unterschiede gelten für |und ||. Das Wichtigste ist, dass &&es sich um einen logischen Operator handelt, der nur für boolesche Operanden gilt, während &es sich um einen bitweisen Operator handelt, der sowohl für ganzzahlige Typen als auch für boolesche Typen gilt.

Mit einer logischen Operation können Sie einen Kurzschluss ausführen, da Sie in bestimmten Fällen (wie dem ersten Operanden des &&Seins falseoder dem ersten Operanden des ||Seins true) den Rest des Ausdrucks nicht auswerten müssen. Dies ist sehr nützlich, um beispielsweise nullvor dem Zugriff auf ein Feld oder eine Methode zu prüfen und vor dem Teilen durch mögliche Nullen nach möglichen Nullen zu suchen. Bei einem komplexen Ausdruck wird jeder Teil des Ausdrucks auf dieselbe Weise rekursiv ausgewertet. Zum Beispiel im folgenden Fall:

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

Es werden nur die hervorgehobenen Teile ausgewertet. Um das zu berechnen ||, überprüfen Sie zuerst, ob dies der Fall 7 == 8ist true. Wenn dies der Fall wäre, würde die rechte Seite vollständig übersprungen. Die rechte Seite prüft nur, ob dies der Fall 1 == 3ist false. Da es ist, 4 == 4muss nicht überprüft werden, und der gesamte Ausdruck wird ausgewertet false. Wenn die linke Seite truez. B. 7 == 7anstelle von wäre 7 == 8, würde die gesamte rechte Seite übersprungen, da der gesamte ||Ausdruck trueunabhängig wäre.

Bei einer bitweisen Operation müssen Sie alle Operanden auswerten, da Sie wirklich nur die Bits kombinieren. Boolesche Werte sind in Java praktisch eine Ein-Bit-Ganzzahl (unabhängig davon, wie die Interna funktionieren), und es ist nur ein Zufall, dass Sie in diesem einen speziellen Fall einen Kurzschluss für bitweise Operatoren durchführen können. Der Grund dafür, dass Sie eine allgemeine Ganzzahl &oder |Operation nicht kurzschließen können, besteht darin, dass einige Bits in beiden Operanden aktiviert und andere deaktiviert sind. So etwas 1 & 2ergibt Null, aber Sie können das nicht wissen, ohne beide Operanden auszuwerten.


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

Da die Kurzschlussform von AND (&&) verwendet wird, besteht kein Risiko, eine Laufzeitausnahme zu verursachen, wenn der Dämon Null ist.

Ref. Java 2 Fifth Edition von Herbert Schildt

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.