Frage Verknüpfung "or-assignment" (| =) Operator in Java


Ich habe eine lange Reihe von Vergleichen in Java, und ich würde gerne wissen, ob einer oder mehrere von ihnen als wahr herauskommen. Die Reihe der Vergleiche war lang und schwer zu lesen, also habe ich sie aus Gründen der Lesbarkeit getrennt und automatisch einen Shortcut-Operator verwendet |= eher, als negativeValue = negativeValue || boolean.

boolean negativeValue = false;
negativeValue |= (defaultStock < 0);
negativeValue |= (defaultWholesale < 0);
negativeValue |= (defaultRetail < 0);
negativeValue |= (defaultDelivery < 0);

ich erwarte negativeValue um wahr zu sein, wenn einer der Standardwerte <etwas> negativ ist. Ist das gültig? Wird es tun, was ich erwarte? Ich konnte es nicht auf Suns Website oder Stackoverflow erwähnt sehen, aber Eclipse scheint kein Problem damit zu haben und der Code kompiliert und läuft.


Wenn ich mehrere logische Schnittpunkte ausführen möchte, könnte ich das auch verwenden &= Anstatt von &&?


75
2018-03-21 09:06


Ursprung


Antworten:


Das |= ist ein zusammengesetzter Zuweisungsoperator (JLS 15.26.2) für den booleschen logischen Operator | (JLS 15.22.2); nicht mit dem Conditional-oder zu verwechseln || (JLS 15.24). Es gibt auch &= und ^= entsprechend der zusammengesetzten Zuweisungsversion des logischen Boolean & und ^ beziehungsweise.

Mit anderen Worten, für boolean b1, b2, diese beiden sind gleichwertig:

 b1 |= b2;
 b1 = b1 | b2;

Der Unterschied zwischen den logischen Operatoren (& und |) im Vergleich zu ihren bedingten Gegenstücken (&& und ||) ist, dass ersteres nicht "shortcircuit"; Letzteres tun. Das ist:

  • & und |  immer werte beide Operanden aus
  • && und || werte den richtigen Operanden aus bedingt; Der rechte Operand wird nur ausgewertet, wenn sein Wert das Ergebnis der binären Operation beeinflussen könnte. Das bedeutet, dass der richtige Operand NICHT ausgewertet wird, wenn
    • Der linke Operand von && bewertet zu false
      • (Denn egal, was der rechte Operand auswertet, ist der gesamte Ausdruck false)
    • Der linke Operand von || bewertet zu true
      • (Denn egal, was der rechte Operand auswertet, ist der gesamte Ausdruck true)

Also zurück zu Ihrer ursprünglichen Frage, ja, dieses Konstrukt ist gültig und während |= ist nicht genau eine äquivalente Abkürzung für = und ||Es berechnet, was Sie wollen. Da die rechte Seite der |= Operator in Ihrer Verwendung ist eine einfache Ganzzahl Vergleichsoperation, die Tatsache, dass | kein Kurzschluss ist unbedeutend.

Es gibt Fälle, in denen ein Kurzschluss erwünscht oder sogar erforderlich ist, aber Ihr Szenario gehört nicht dazu.

Es ist bedauerlich, dass Java im Gegensatz zu einigen anderen Sprachen nicht hat &&= und ||=. Dies wurde in der Frage diskutiert Warum hat Java keine zusammengesetzten Zuweisungsversionen der Bedingungs- und Bedingungsoperatoren? (&& =, || =).


183
2018-03-21 09:44



Es ist kein "Abkürzungs" (oder Kurzschließer) Operator in der Art, dass || und && sind (indem sie die RHS nicht bewerten, wenn sie das Ergebnis bereits auf der LHS kennen), aber es wird tun, was Sie in Bezug auf Arbeiten.

Als Beispiel für den Unterschied ist dieser Code in Ordnung, wenn text ist Null:

boolean nullOrEmpty = text == null || text.equals("")

in der Erwägung, dass dies nicht

boolean nullOrEmpty = false;
nullOrEmpty |= text == null;
nullOrEmpty |= text.equals(""); // Throws exception if text is null

(Natürlich könnten Sie das tun "".equals(text) für diesen speziellen Fall - ich versuche nur, das Prinzip zu demonstrieren.)


16
2018-03-21 09:12



Sie könnten nur eine Aussage haben. Über mehrere Zeilen ausgedrückt liest es sich fast genau wie Ihr Beispielcode, nur weniger zwingend:

boolean negativeValue
    = defaultStock < 0 
    | defaultWholesale < 0
    | defaultRetail < 0
    | defaultDelivery < 0;

Für einfachste Ausdrücke verwenden | kann schneller sein als || Denn auch wenn man einen Vergleich vermeidet, bedeutet dies implizit eine Verzweigung, die um ein Vielfaches teurer sein kann.


3
2018-03-21 10:14



Obwohl es für Ihr Problem vielleicht übertrieben ist, das Guave Bibliothek hat einige nette Syntax mit Predicates und macht eine Kurzschlussauswertung von oder / und Predicates.

Im Wesentlichen werden die Vergleiche in Objekte umgewandelt, in eine Sammlung verpackt und dann über iteriert. Für oder Prädikate kehrt der erste wahre Treffer von der Iteration zurück und umgekehrt für und.


1
2018-03-22 14:28



Wenn es um Lesbarkeit geht, habe ich das Konzept der Trennung getestet Daten aus der Testlogik. Codebeispiel:

// declare data
DataType [] dataToTest = new DataType[] {
    defaultStock,
    defaultWholesale,
    defaultRetail,
    defaultDelivery
}

// define logic
boolean checkIfAnyNegative(DataType [] data) {
    boolean negativeValue = false;
    int i = 0;
    while (!negativeValue && i < data.length) {
        negativeValue = data[i++] < 0;
    }
    return negativeValue;
}

Der Code sieht verständlicher und selbsterklärend aus. Sie können sogar ein Array im Methodenaufruf wie folgt erstellen:

checkIfAnyNegative(new DataType[] {
    defaultStock,
    defaultWholesale,
    defaultRetail,
    defaultDelivery
});

Es ist besser lesbar als 'Vergleichszeichenfolge' und hat auch einen Leistungsvorteil beim Kurzschließen (auf Kosten von Array-Zuweisung und Methodenaufruf).

Bearbeiten: Noch mehr Lesbarkeit kann einfach durch die Verwendung von Varargs-Parametern erreicht werden:

Methodensignatur wäre:

boolean checkIfAnyNegative(DataType ... data)

Und der Anruf könnte so aussehen:

checkIfAnyNegative( defaultStock, defaultWholesale, defaultRetail, defaultDelivery );

1
2018-04-25 09:38



List<Integer> params = Arrays.asList (defaultStock, defaultWholesale, 
                                       defaultRetail, defaultDelivery);
int minParam = Collections.min (params);
negativeValue = minParam < 0;

0
2018-03-21 09:15



|| logisches Boolesches ODER
| bitweise ODER

| = bitweise inklusive ODER- und Zuweisungsoperator

Der Grund, warum | = nicht kurzschließt, ist, weil es ein bitweises ODER nicht ein logisches ODER ist. Das heißt:


C | = 2 ist gleich wie C = C | 2

Tutorial für Java-Operatoren


0
2018-01-11 19:15