Effect of a Bitwise Operator on a Boolean in Java
The operators &
, ^
, and |
are bitwise operators when the operands are primitive integral types. They are logical operators when the operands are boolean, and their behaviour in the latter case is specified. See the section 15.22.2 of the Java Language Specification for details.
Why are bitwise operators slower at comparing booleans than the normal ones in Java?
Louis Wasserman's comment is the correct diagnosis. The number of calls to the random number generator strongly affects the performance, so short-circuiting is important. I modified the program to count the numbers of calls using a couple of methods like this:
private static boolean normalCountedRandom() {
normalCount++;
return rng.nextBoolean();
}
I also did multiple measurements in each run to eliminate any issue of start-up effects. A typical output was:
Bitwise operator: 1985
Normal operator: 1560
Bitwise operator: 1967
Normal operator: 1547
Bitwise operator: 2046
Normal operator: 1557
Bitwise operator: 2009
Normal operator: 1553
Bitwise Random calls: 800006428
Normal Random calls: 600030931
The 4:3 ratio is as expected. Each if
does one compulsory call. If using a short circuit operator, only half of those will result in a second call, for an expected 1.5 calls per if
, compared to 2 per if
without the short-circuit. This ratio is similar to the performance ratio, assuming the calls account for most, but not all, of the time.
The short-circuit behavior is documented in the JLS. Technically, when applied to boolean operands, &
and |
are Boolean Logical Operators. The "normal" operators are Conditional-And and Conditional-Or Operators.
It is generally better to avoid having the number of iterations depend on a Random
result, although in this case, with enough iterations, the variance between runs is small.
Are the &, |, ^ bitwise operators or logical operators?
The Java operators &
, |
and ^
are EITHER bitwise operators OR logical operators ... depending on the types of the operands. If the operands are integers, the operators are bitwise. If they are booleans, then the operators are logical.
And this is not just me saying this. The JLS describes these operators this way too; see JLS 15.22.
(This is just like +
meaning EITHER addition OR string concatenation ... depending on the types of the operands. Or just like a "rose" meaning either a flower or a shower attachment. Or "cat" meaning either a furry animal or a UNIX command. Words mean different things in different contexts. And this is true for the symbols used in programming languages too.)
There are already logical operators
&&
,||
, why use&
,|
,^
?
In the case of the first two, it is because the operators have different semantics with regards to when / whether the operands get evaluated. The two different semantics are needed in different situations; e.g.
boolean res = str != null && str.isEmpty();
versus
boolean res = foo() & bar(); // ... if I >>need<< to call both methods.
The ^
operator has no short-circuit equivalent because it simply doesn't make sense to have one.
Java boolean |= operator
From the JLS:
15.26.2. Compound Assignment Operators
A compound assignment expression of the form
E1 op= E2
is equivalent toE1 = (T) ((E1) op (E2))
, whereT
is the type ofE1
, except thatE1
is evaluated only once.15.22.2. Boolean Logical Operators
&
,^
, and|
When both operands of a
&
,^
, or|
operator are of typeboolean
orBoolean
, then the type of the bitwise operator expression isboolean
. In all cases, the operands are subject to unboxing conversion (§5.1.8) as necessary.For
|
, the result value is false if both operand values are false; otherwise, the result is true.
This means that
val |= somethingElse();
is strictly equivalent to
val = val | somethingElse();
(assuming somethingElse()
returns boolean
or Boolean
).
I'd be curious if right operand is evaluated if left value already is true.
Yes, it would be evaluated, since |
does not short-circuit:
15.7.2. Evaluate Operands before Operation
The Java programming language guarantees that every operand of an operator (except the conditional operators
&&
,||
, and? :
) appears to be fully evaluated before any part of the operation itself is performed.15.24. Conditional-Or Operator
||
Thus,
||
computes the same result as|
onboolean
orBoolean
operands. It differs only in that the right-hand operand expression is evaluated conditionally rather than always.
Why do we usually use || over |? What is the difference?
If you use the ||
and &&
forms, rather than the |
and &
forms of these operators, Java will not bother to evaluate the right-hand operand alone.
It's a matter of if you want to short-circuit the evaluation or not -- most of the time you want to.
A good way to illustrate the benefits of short-circuiting would be to consider the following example.
Boolean b = true;
if(b || foo.timeConsumingCall())
{
//we entered without calling timeConsumingCall()
}
Another benefit, as Jeremy and Peter mentioned, for short-circuiting is the null reference check:
if(string != null && string.isEmpty())
{
//we check for string being null before calling isEmpty()
}
more info
Is there a difference between using a logical operator or a bitwise operator in an if block in Java?
The logical operator works on booleans, and the bitwise operator works on bits. In this case, the effect is going to be the same, but there are two differences:
- The bitwise operator is not meant for that, which makes it harder to read but most importantly
- The logical OR operator will evaluate the first condition. If it's true, it does not matter what the next condition results in, the result will be true, so the second clause is not executed
Here's some handy code to prove this:
public class OperatorTest {
public static void main(String[] args){
System.out.println("Logical Operator:");
if(sayAndReturn(true, "first") || sayAndReturn(true, "second")){
//doNothing
}
System.out.println("Bitwise Operator:");
if(sayAndReturn(true, "first") | sayAndReturn(true, "second")){
//doNothing
}
}
public static boolean sayAndReturn(boolean ret, String msg){
System.out.println(msg);
return ret;
}
}
is there any other use of & other than bitwise AND
&
can be applied on two boolean
operands as a non short circuiting version of binary AND operator (unlike the short circuiting &&
operator).
|
can be applied on two boolean
operands as a non short circuiting version of binary OR operator (unlike the short circuiting ||
operator).
^
(XOR) can also be applied on two boolean
operands.
To summarize, all 3 operators can serve as boolean operators (when applied to boolean
operands) or bit-wise operators (when applies to integer operands).
These operators are described in JLS 15.22.2.:
15.22.2. Boolean Logical Operators &, ^, and |
When both operands of a &, ^, or | operator are of type boolean or Boolean, then the type of the bitwise operator expression is boolean. In all cases, the operands are subject to unboxing conversion (§5.1.8) as necessary.
For &, the result value is true if both operand values are true; otherwise, the result is false.
For ^, the result value is true if the operand values are different; otherwise, the result is false.
For |, the result value is false if both operand values are false; otherwise, the result is true.
Boolean bitwise and logical operators
As noted in the comments, you should use logical operators when you're doing logic and bitwise operators when doing bitwise operations.
One of the main differences among these is that C++ will short-circuit the logical operations; meaning that it will stop evaluating the operands as soon as it's clear what the result of the operation is.
As an example, this code:
bool foo() {
std::puts("foo");
return true;
}
bool bar() {
std::puts("bar");
return true;
}
//...
auto const res = foo() || bar();
will only output:
foo
Function bar
won't be evaluated as, in this case, evaluating foo
is enough to know the result of expression foo() || bar()
is true
.
Related Topics
What Is the Optimal Capacity and Load Factor for a Fixed-Size Hashmap
How Does Java Object Casting Work Behind the Scene
How to Autowire Bean of Generic Type <T> in Spring
How to Check a Uploaded File Whether It Is an Image or Other File
Sessiontimeout: Web.Xml VS Session.Maxinactiveinterval()
What Is the Most Recommended Way to Store Time in Postgresql Using Java
Hashmap Implementation in Java. How Does the Bucket Index Calculation Work
Find Duplicate Element in Array in Time O(N)
How to Simulate a Real Mouse Click Using Java
Java Threads and Number of Cores
How to Read a Text-File Resource into Java Unit Test
Use a .Jar Java Library API in C#
Hashmap to Return Default Value for Non-Found Keys
Import Sun.Misc.Base64Encoder Results in Error Compiled in Eclipse
Waiting at Sun.Misc.Unsafe.Park(Native Method)
Copying Text to the Clipboard Using Java