Shortcut "or-assignment" (|=) operator in Java
The |=
is a compound assignment operator (JLS 15.26.2) for the boolean logical operator |
(JLS 15.22.2); not to be confused with the conditional-or ||
(JLS 15.24). There are also &=
and ^=
corresponding to the compound assignment version of the boolean logical &
and ^
respectively.
In other words, for boolean b1, b2
, these two are equivalent:
b1 |= b2;
b1 = b1 | b2;
The difference between the logical operators (&
and |
) compared to their conditional counterparts (&&
and ||
) is that the former do not "shortcircuit"; the latter do. That is:
&
and|
always evaluate both operands&&
and||
evaluate the right operand conditionally; the right operand is evaluated only if its value could affect the result of the binary operation. That means that the right operand is NOT evaluated when:- The left operand of
&&
evaluates tofalse
- (because no matter what the right operand evaluates to, the entire expression is
false
)
- (because no matter what the right operand evaluates to, the entire expression is
- The left operand of
||
evaluates totrue
- (because no matter what the right operand evaluates to, the entire expression is
true
)
- (because no matter what the right operand evaluates to, the entire expression is
- The left operand of
So going back to your original question, yes, that construct is valid, and while |=
is not exactly an equivalent shortcut for =
and ||
, it does compute what you want. Since the right hand side of the |=
operator in your usage is a simple integer comparison operation, the fact that |
does not shortcircuit is insignificant.
There are cases, when shortcircuiting is desired, or even required, but your scenario is not one of them.
It is unfortunate that unlike some other languages, Java does not have &&=
and ||=
. This was discussed in the question Why doesn't Java have compound assignment versions of the conditional-and and conditional-or operators? (&&=, ||=).
It's not a "shortcut" (or short-circuiting) operator in the way that || and && are (in that they won't evaluate the RHS if they already know the result based on the LHS) but it will do what you want in terms of working.
As an example of the difference, this code will be fine if text
is null:
boolean nullOrEmpty = text == null || text.equals("")
whereas this won't:
boolean nullOrEmpty = false;
nullOrEmpty |= text == null;
nullOrEmpty |= text.equals(""); // Throws exception if text is null
(Obviously you could do "".equals(text)
for that particular case - I'm just trying to demonstrate the principle.)
You could just have one statement. Expressed over multiple lines it reads almost exactly like your sample code, only less imperative:
boolean negativeValue
= defaultStock < 0
| defaultWholesale < 0
| defaultRetail < 0
| defaultDelivery < 0;
For simplest expressions, using |
can be faster than ||
because even though it avoids doing a comparison it means using a branch implicitly and that can be many times more expensive.