Auswirkung eines bitweisen Operators auf einen Booleschen Wert in Java

118

Die bitweisen Operatoren sollen Variablen übertragen und Stück für Stück bearbeiten. Bei ganzen Zahlen, Longs und Zeichen ist dies sinnvoll. Diese Variablen können den gesamten Wertebereich enthalten, der durch ihre Größe erzwungen wird.

Bei Booleschen Werten kann ein Boolescher Wert jedoch nur zwei Werte enthalten. 1 = wahr oder 0 = falsch. Die Größe des Booleschen Werts ist jedoch nicht definiert. Es kann so groß wie ein Byte oder so klein wie ein bisschen sein.

Wie wirkt sich die Verwendung eines bitweisen Operators auf einen Booleschen Wert aus? Übersetzt die JVM sie im Wesentlichen in einen normalen logischen Operator und fährt fort? Behandelt es den Booleschen Wert für die Operation als Einzelbit-Entität? Oder ist das Ergebnis zusammen mit der Größe eines Booleschen Werts undefiniert?

Daniel Bingham
quelle
1
Ich denke, Sie können keinen bitweisen Operator für einen Booleschen Wert verwenden. Nur auf Zahlen. Ich bin sicher, ~ wird nicht funktionieren, ich weiß nicht, was mit anderen Betreibern ist.
Martijn Courteaux
4
Sie können einige davon verwenden, wir haben gerade ein | entdeckt wird in unserem Legacy-Code verwendet. Wir entfernen es, aber dieser Code wurde kompiliert und funktioniert.
Daniel Bingham
9
Da einer kurzschließt und der andere nicht (siehe die Antwort von mobrule), bevor Sie | ändern zu || Möglicherweise möchten Sie sicherstellen, dass die nachfolgenden booleschen Ausdrücke keine Nebenwirkungen haben, die der ursprüngliche Programmierer immer ausführen wollte.
John M Gant

Antworten:

122

Die Operatoren &, ^und |sind bitweise Operatoren, wenn die Operanden primitive Integraltypen sind. Sie sind logische Operatoren, wenn die Operanden boolesch sind, und ihr Verhalten im letzteren Fall wird angegeben. Weitere Informationen finden Sie in Abschnitt 15.22.2 der Java-Sprachspezifikation .

Noel Ang
quelle
56
Insbesondere & und ^ und | sind die logischen booleschen Operatoren ohne Kurzschluss.
Ken
14
Hier ist ein direkter Link zu dem oben genannten Abschnitt: docs.oracle.com/javase/specs/jls/se7/html/…
Andy Thomas
Wenn das oben Gesagte zutrifft, warum löst ideone.com/oGSF7c eine Nullzeigerausnahme aus? Wenn der |=Operator logisch war, sollte das Programm die x.getValue()Direktive niemals ausgeführt haben .
ikromm
1
@ JohnKrommidas, dein x ist null, weshalb du eine NullPointerException bekommst. Sie müssen es instanziieren.
Ben
4
@Ben, Wie @Ken sagt, ist die Logik nicht kurzgeschlossen, daher wird der zweite Teil ausgewertet. a || x.foo()Ist also sicher, wenn x null ist, aber a | x.foo()nicht. |=folgt den gleichen Regeln wie |.
Michael Smith
86

Die Verwendung des bitweisen Operators kann das Kurzschlussverhalten umgehen:

boolean b = booleanExpression1() && booleanExpression2();
boolean b = booleanExpression1() & booleanExpression2();

Wenn booleanExpression1()bewertet false,
booleanExpression2()wird im ersten Fall nicht bewertet, und
booleanExpression2()(und welche Nebenwirkungen es auch haben mag) wird im zweiten Fall bewertet.

Mob
quelle
2
Und die bitweise Operation ist normalerweise schneller als die Kurzschlussoperation (vorausgesetzt, die Auswertung ist einfach)
Uhr
1
Das bitweise &wird schneller sein, aber der Aufruf der zweiten Funktion könnte mit der Verwendung von&&
NatNgs
20

Darüber hinaus , was in den anderen Antworten bedeckt ist, unter Hinweis darauf , es wert ist, dass &&und ||haben unterschiedliche Priorität von &und |.

Auszug aus der Prioritätstabelle (mit der höchsten Priorität oben).

bitwise AND                 &
bitwise exclusive OR        ^
bitwise inclusive OR        |
logical AND                 &&
logical OR                  ||

Was bedeutet das für Sie?

Absolut nichts, solange Sie sich entweder nur &und |oder nur &&und halten ||.

Da sie jedoch |eine höhere Priorität haben als &&(im Gegensatz zu einer ||niedrigeren Priorität), kann das freie Mischen zu unerwartetem Verhalten führen.

So a && b | c && dist das gleiche wie a && (b | c) && d,
im Gegensatz zu a && b || c && ddem , was wäre (a && b) || (c && d).

Um zu beweisen, dass sie nicht gleich sind, betrachten Sie einen Auszug aus der Wahrheitstabelle:

a | b | c | d | (b|c) | (a&&b) | (c&&d) | a && (b|c) && d | (a&&b) || (c&&d)
F | T | T | T |   T   |   F    |    T   |         F       |        T
                                                  ^                ^
                                                  |- not the same -|

Wenn Sie wollen oder eine höhere Priorität haben als AND, Sie könnten nutzen |und &&zusammen, aber dies wird nicht empfohlen.

Aber Sie sollten sie wirklich in Klammern setzen, um die Priorität zu verdeutlichen, wenn Sie verschiedene Symbole verwenden, dh (a && b) || c(Klammern, um die Priorität zu verdeutlichen) a && b && c(keine Klammern erforderlich).

Bernhard Barker
quelle
3

Auch wenn es funktionieren wird, sollten Sie es nicht tun. Sprachspezifikationen definieren bitweise Operatoren nur, wenn beide Operanden vom primitiven Integer-Typ oder beide vom Booleschen Typ sind. Ich würde für jeden anderen Fall sagen, dass die Ergebnisse nicht definiert sind:

http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#5228

LeffeBrune
quelle
Die Frage bezieht sich auf Boolesche Werte, nicht auf Grundelemente oder eine Mischung aus Grundelementen und Booleschen Werten.
Talonx