Unterschiede in den Booleschen Operatoren: & vs && und | vs ||

Antworten:

134

Dies sind die bitweisen UND- und bitweisen ODER-Operatoren.

int a = 6; // 110
int b = 4; // 100

// Bitwise AND    

int c = a & b;
//   110
// & 100
// -----
//   100

// Bitwise OR

int d = a | b;
//   110
// | 100
// -----
//   110

System.out.println(c); // 4
System.out.println(d); // 6

Vielen Dank an Carlos für den Hinweis auf den entsprechenden Abschnitt in der Java-Sprachspezifikation ( 15.22.1 , 15.22.2 ) bezüglich der unterschiedlichen Verhaltensweisen des Operators basierend auf seinen Eingaben.

Wenn beide Eingaben boolesch sind, werden die Operatoren als boolesche logische Operatoren betrachtet und verhalten sich ähnlich wie die Operatoren Conditional-And ( &&) und Conditional-Or ( ||), mit der Ausnahme, dass sie nicht kurzschließen, solange das Folgende sicher ist ::

if((a != null) && (a.something == 3)){
}

Das ist nicht:

if((a != null) & (a.something == 3)){
}

"Kurzschluss" bedeutet, dass der Bediener nicht unbedingt alle Bedingungen untersucht. In den obigen Beispielen &&wird die zweite Bedingung nur dann untersucht, wenn dies anicht nullder Fall ist (andernfalls wird die gesamte Anweisung false zurückgeben, und es wäre ohnehin a.somethingnicht möglich, die folgenden Bedingungen zu untersuchen), sodass die Anweisung von keine Ausnahme auslöst oder als "sicher" betrachtet wird . "

Der &Operator prüft immer jede Bedingung in der Klausel, sodass in den obigen Beispielen a.somethingbewertet werden kann, ob aes sich tatsächlich um einen nullWert handelt, der eine Ausnahme auslöst.

Justin Niessner
quelle
1
wollte klarstellen .. & wird 1 nur zurückgeben, wenn BEIDE 1 sind? Also wäre 101 & 001 001? Richtig?
Gideon
@giddy @Jonathon - Ich habe meine Werte aktualisiert, um diese Situation besser darzustellen.
Justin Niessner
unvollständig: Sie sind auch logische Operatoren (für Boolesche Werte).
user85421
1
@ Carlos- Nein. Sie sind immer noch bitweise Operatoren. Sie verhalten sich genauso wie logische Operatoren ohne Kurzschluss. Da ist ein Unterschied.
Justin Niessner
4
und was sind die logischen Operatoren ohne Kurzschluss? Die Operatoren & und | (von OP gefragt) sind "Integer Bitwise Operators" (JLS 15.22.1) und "Boolean Logical Operators" (JLS 15.22.2). Oder ist die Java-Sprachspezifikation falsch?
user85421
108

Ich denke, Sie sprechen über die logische Bedeutung beider Operatoren. Hier haben Sie einen Tabellen-Lebenslauf:

boolean a, b;

Operation     Meaning                       Note
---------     -------                       ----
   a && b     logical AND                    short-circuiting
   a || b     logical OR                     short-circuiting
   a &  b     boolean logical AND            not short-circuiting
   a |  b     boolean logical OR             not short-circuiting
   a ^  b     boolean logical exclusive OR
  !a          logical NOT

short-circuiting        (x != 0) && (1/x > 1)   SAFE
not short-circuiting    (x != 0) &  (1/x > 1)   NOT SAFE

Kurzschlussauswertung , Minimalauswertung oder McCarthy-Auswertung (nach John McCarthy) ist die Semantik einiger Boolescher Operatoren in einigen Programmiersprachen, in denen das zweite Argument nur ausgeführt oder ausgewertet wird, wenn das erste Argument nicht ausreicht, um den Wert von zu bestimmen Ausdruck: Wenn das erste Argument der AND-Funktion false ergibt, muss der Gesamtwert false sein. und wenn das erste Argument der ODER-Funktion als wahr ausgewertet wird, muss der Gesamtwert wahr sein.

Nicht sicher bedeutet, dass der Operator immer jede Bedingung in der Klausel untersucht. In den obigen Beispielen kann 1 / x ausgewertet werden, wenn x tatsächlich ein 0-Wert ist, was eine Ausnahme auslöst.

Torres
quelle
1
@Torres - Bitte erweitern Sie Ihre Antwort, indem Sie "Kurzschluss" und "sicher" erklären. Ist auch "exklusiv oder" und "logisch nicht" auch "nicht kurzgeschlossen"? Und warum heißt es "logisch nicht" statt "boolesches logisch nicht"? Und warum wird das "logische NICHT" nicht mit dem "logischen UND" und dem "logischen ODER" gruppiert? Gute Antwort, braucht aber Arbeit.
Montag,
@tfmontague, ich habe erklärt, was Kurzschluss bedeutet (indem ich diese Antwort bearbeite). Ich warte darauf, dass meine Bearbeitung "Peer Review" wird.
Taslim Oseni
Was ist "unsicher" daran, nicht kurzzuschließen? Sollte es nicht sicherer sein als Kurzschlüsse? Übrigens: Sie erklären den Begriff "Kurzschluss" nicht wirklich. Dies bedeutet, dass bei "nicht Kurzschluss" zuerst alle Teile ausgewertet werden, dann wird die Boolesche Operation angewendet, während bei Kurzschluss die Auswertung gestoppt wird, wenn der erste Ausdruck die Bedingung erfüllt, wie dies bei (a || b) nicht der Fall ist bewerte b, wenn a wahr ist und die Operation oder wahr zurückgibt, egal was b ist.
SCI
26

Ich weiß, dass es hier viele Antworten gibt, aber sie scheinen alle etwas verwirrend. Nachdem ich einige Nachforschungen im Java Oracle Study Guide angestellt habe, habe ich drei verschiedene Szenarien für die Verwendung von && oder & entwickelt. Die drei Szenarien sind logisches UND , bitweises UND und boolesches UND .

Logisches UND: Das logische UND (auch als bedingtes UND bezeichnet) verwendet den Operator && . Es ist eine kurzgeschlossene Bedeutung: Wenn der linke Operand falsch ist, wird der rechte Operand nicht ausgewertet.
Beispiel:

int x = 0;
if (false && (1 == ++x) {
    System.out.println("Inside of if");
}
System.out.println(x); // "0"

Im obigen Beispiel ist der Wert, der an die Konsole von x gedruckt wird, 0, da der erste Operand in der if-Anweisung falsch ist. Daher muss Java nicht berechnen (1 == ++ x), daher wird x nicht berechnet.

Bitweises UND: Bitweises UND verwendet den Operator & . Es wird verwendet, um eine bitweise Operation für den Wert durchzuführen. Es ist viel einfacher zu sehen, was los ist, wenn man sich die Operation für Binärzahlen ansieht, z.

int a = 5;     //                    5 in binary is 0101
int b = 12;    //                   12 in binary is 1100
int c = a & b; // bitwise & preformed on a and b is 0100 which is 4

Wie Sie im Beispiel sehen können, erzeugt ein bitweises UND, das vorgeformt ist, nur eine Binärzahl, wenn dieselbe Binärdarstellung der Zahlen 5 und 12 ausgerichtet ist, wobei dieselbe Ziffer in beiden Zahlen eine 1 hat. Daher 0101 & 1100 == 0100. Was in Dezimalzahl 5 & 12 == 4 ist.

Boolesches UND: Jetzt verhält sich der boolesche UND-Operator ähnlich und unterschiedlich wie das bitweise UND und das logische UND. Ich stelle es mir gerne als ein bitweises UND zwischen zwei booleschen Werten (oder Bits) vor, daher wird es verwendet Operator & . Die booleschen Werte können auch das Ergebnis eines logischen Ausdrucks sein.

Es gibt entweder einen wahren oder einen falschen Wert zurück, ähnlich wie das logische UND, aber im Gegensatz zum logischen UND ist es nicht kurzgeschlossen. Der Grund dafür ist, dass es den Wert sowohl des linken als auch des rechten Operanden kennen muss, damit es dieses bitweise UND vorformt. Hier ist ein Ex:

int x = 0;
if (false & (1 == ++x) {
    System.out.println("Inside of if");
}
System.out.println(x); //"1"

Wenn diese if-Anweisung ausgeführt wird, wird der Ausdruck (1 == ++ x) ausgeführt, obwohl der linke Operand falsch ist. Daher ist der für x ausgedruckte Wert 1, da er inkrementiert wurde.

Dies gilt auch für logisches ODER (||), bitweises ODER (|) und boolesches ODER (|). Ich hoffe, dies beseitigt einige Verwirrung.

LynchburgExplorer
quelle
to preform that bitwise AND, it must know the value of both left and right operandsDas klingt für mich nicht richtig. Um a auszuführen, müssen BITWISE ANDSie nicht den richtigen Operanden kennen, um das Ergebnis herausfinden zu können, wenn der linke Operand ist FALSE. Was Sie erklären, ist richtig, aber die Argumentation, die Sie angeben, scheint mir zumindest nicht so zu sein.
Koray Tugay
7

Die Operatoren && und || sind kurzgeschlossen, was bedeutet, dass sie ihren rechten Ausdruck nicht bewerten, wenn der Wert des linken Ausdrucks ausreicht, um das Ergebnis zu bestimmen.

Tassos Bassoukos
quelle
7
-1 dafür, dass er dem OP erzählt hat, was er bereits wusste, und die Frage, die er tatsächlich gestellt hat, nicht beantwortet hat.
Alnitak
5

& und | liefern das gleiche Ergebnis wie && und || Betreiber. Der Unterschied besteht darin, dass sie immer beide Seiten des Ausdrucks als && und || auswerten Beenden Sie die Bewertung, wenn die erste Bedingung ausreicht, um das Ergebnis zu bestimmen.

Brian Scott
quelle
1
Falsch .... Denn &&es bewertet beide Ergebnisse, während es ||nur zurückgibt, wenn die erste Bedingung erfüllt ist.
Buhake Sindi
1
Huh? Das && wertet die rechte Seite des Ausdrucks nur aus, wenn die linke Seite bereits als wahr ausgewertet wird. Andernfalls wird die Auswertung gestoppt, da das erste falsche implizit bedeutet, dass das Ergebnis nicht wahr sein kann. Siehe jguru.com/faq/view.jsp?EID=16530
Brian Scott
1
( 2 & 4 )bewertet zu false, während ( 2 && 4 )bewertet zu true. Wie genau ist das das gleiche Ergebnis?
Piskvor verließ das Gebäude
1
@Piskvor - nicht in Java! 2 & 4führt zu einer Ganzzahl, nicht zu einem Booleschen Wert (in diesem Fall Null). 2 && 4wird nicht kompiliert, && akzeptiert nur Boolesche Werte. Java erlaubt nicht das Mischen von Booleschen und Ints: Null ist nicht false, falseist nicht Null ...
user85421
1
@BuhakeSindi Falsch. Denn &&es wertet den zweiten Operanden nur aus, wenn der erste Operand ist true.
Marquis von Lorne
2

In Java sind die einzelnen Operatoren &, |, ^ ,! hängen von den Operanden ab. Wenn beide Operanden Ints sind, wird eine bitweise Operation ausgeführt. Wenn beide Boolesche Werte sind, wird eine "logische" Operation ausgeführt.

Wenn beide Operanden nicht übereinstimmen, wird ein Fehler bei der Kompilierung ausgelöst.

Die Doppeloperatoren &&, || verhalten sich ähnlich wie ihre einzelnen Gegenstücke, aber beide Operanden müssen bedingte Ausdrücke sein, zum Beispiel:

if ((a <0) && (b <0)) {...} oder ähnlich if ((a <0) || (b <0)) {...}

Quelle: Java-Programmierung lang 4th ed

aaron p.
quelle
1

Vielleicht kann es nützlich sein zu wissen, dass die bitweisen UND- und bitweisen ODER-Operatoren immer vor dem bedingten UND und dem bedingten ODER ausgewertet werden, die im selben Ausdruck verwendet werden.

if ( (1>2) && (2>1) | true) // false!
alexmeia
quelle
1
Meinen Sie eher Betreiberpriorität als Bewertungsreihenfolge? Ich würde den Prioritätsunterschied, der in echtem Code verwendet wird, lieber nicht sehen. Verwenden Sie zu diesem Zweck Klammern anstelle von bitweisen Operatoren.
John Dvorak
1

&&; || sind logische Operatoren .... Kurzschluss

&; | sind boolesche logische Operatoren .... Nicht kurzgeschlossen

Übergang zu Unterschieden in der Ausführung von Ausdrücken. Bitweise Operatoren bewerten beide Seiten unabhängig vom Ergebnis der linken Seite. Bei der Auswertung von Ausdrücken mit logischen Operatoren hängt die Auswertung des rechten Ausdrucks jedoch von der Bedingung der linken Hand ab.

Beispielsweise:

int i = 25;
int j = 25;
if(i++ < 0 && j++ > 0)
    System.out.println("OK");
System.out.printf("i = %d ; j = %d",i,j);

Dies gibt i = 26 aus; j = 25, Da die erste Bedingung falsch ist, wird die Bedingung für die rechte Hand umgangen, da das Ergebnis unabhängig von der Bedingung für die rechte Seite sowieso falsch ist. (Kurzschluss)

int i = 25;
int j = 25;
if(i++ < 0 & j++ > 0)
    System.out.println("OK");
System.out.printf("i = %d ; j = %d",i,j);

Dies gibt jedoch i = 26 aus; j = 26,

Nickhil
quelle
0

Wenn ein Ausdruck mit dem Operator Boolean & ausgewertet wird, werden beide Operanden ausgewertet. Dann wird der Operator & auf den Operanden angewendet.

Wenn ein Ausdruck mit dem Operator && ausgewertet wird, wird der erste Operand ausgewertet. Wenn der erste Operand als falsch ausgewertet wird, wird die Auswertung des zweiten Operanden übersprungen.

Wenn der erste Operand den Wert true zurückgibt, wird der zweite Operand ausgewertet. Wenn der zweite Operand den Wert true zurückgibt, wird der Operator && auf den ersten und den zweiten Operanden angewendet.

Ähnliches gilt für | und ||.

RishiKesh Pathak
quelle
0

Während der grundlegende Unterschied darin besteht, dass er &hauptsächlich für bitweise Operationen verwendet longwird intoder bytewo er für eine Art Maske verwendet werden kann, können die Ergebnisse unterschiedlich sein, selbst wenn Sie ihn anstelle von logisch verwenden &&.

Der Unterschied ist in einigen Szenarien deutlicher:

  1. Das Auswerten einiger Ausdrücke ist zeitaufwändig
  2. Die Auswertung eines Ausdrucks kann nur erfolgen, wenn der vorherige wahr ist
  3. Die Ausdrücke haben einige Nebenwirkungen (beabsichtigt oder nicht)

Der erste Punkt ist recht einfach, er verursacht keine Fehler, dauert aber länger. Wenn Sie mehrere verschiedene Prüfungen in einer bedingten Anweisung haben, setzen Sie diejenigen, die entweder billiger sind oder eher scheitern, nach links.

Für den zweiten Punkt siehe dieses Beispiel:

if ((a != null) & (a.isEmpty()))

Dies schlägt fehl null, da die Auswertung des zweiten Ausdrucks a ergibt NullPointerException. Der logische Operator &&ist faul. Wenn der linke Operand falsch ist, ist das Ergebnis falsch, egal welcher rechte Operand ist.

Beispiel für den dritten Punkt - Nehmen wir an, wir haben eine App, die DB ohne Trigger oder Kaskaden verwendet. Bevor wir ein Gebäudeobjekt entfernen, müssen wir das Gebäude eines Abteilungsobjekts in ein anderes ändern. Angenommen, der Operationsstatus wird als Boolescher Wert zurückgegeben (true = success). Dann:

if (departmentDao.update(department, newBuilding) & buildingDao.remove(building))

Dies wertet beide Ausdrücke aus und führt somit das Entfernen von Gebäuden durch, selbst wenn die Abteilungsaktualisierung aus irgendeinem Grund fehlgeschlagen ist. Mit &&funktioniert es wie vorgesehen und stoppt nach dem ersten Ausfall.

Was a || bäquivalent ist !(!a && !b), es hört auf, wenn aes wahr ist , es ist keine weitere Erklärung erforderlich.

Vlasec
quelle