Did you know that Java has three "and" operators?
First, there is the very common logical and: &&:
if (x >= min && x <= max) { … }
Then, there is the bitwise and operator, which very few
programmers will probably ever use:
if (x & 1 != 0) { … }
And finally, there is…
public static boolean isBetween(int x, int min, int max) {
boolean result = (x >= min) & (x <= max);
return result;
}
Take a close look at this code. The expression calculated for
result uses what looks like the bitwise and operator, and yet it
seems to operate on boolean values (respectively x >= min and x <=
max) and not scalar ones.
There are actually two startling things in this code:
- & operating on booleans.
- The result of & being a boolean, and not a scalar.
The solution to the puzzle is given in the Java Language Specification,
chapter 15.22.2:
15.22.2 Boolean Logical Operators &, ^, and |
When both operands of
a&
,^
, or|
operator are of type
boolean
, then the type of the bitwise operator expression is
boolean
.
For&
, the result value istrue
if both operand
values aretrue
; otherwise, the result isfalse
.
For^
, the result value istrue
if the operand
values are different; otherwise, the result isfalse
.
For|
, the result value isfalse
if both operand
values arefalse
; otherwise, the result istrue
.
For all intents and purposes, it looks like the boolean logical &
operator is exactly similar to the logical && operator. Is that
so? Not really. If you run the following program:
public static boolean f() {
System.out.println("false");
return false;
}public static void main(String[] args) {
System.out.println("&&");
boolean a = f() && f();
System.out.println("&");
boolean b = f() & f();
}
You will get the following result:
&&
false
&
false
false
As you can see, && will skip the second expression if the first
expression is false (because at this point, it knows that the overall result
will be false, so there is no point in evaluating the remainder of the
expression) while & will always evaluate all its operands.
Similarly, || will stop evaluating its operands as soon as one is found
to be true while | will always evaluate all of them.
Not surprisingly, logical operators are the most useful because not only do
they typically run faster than their boolean counterparts, they also allow to
write convenient expressions:
if (p != null && p.hasChildren()) { … }
With that in mind, when would you want to use a boolean logical & or
| operator?
The theoretical answer is: whenever your code depends on side effects
performed by the operators involved in the expression and you want to make sure
that all of them are invoked, regardless of the final result of the expression.
Why do I say "theoretical"? Such code would probably qualify as
a design smell because having methods that return a value and perform
side effects are usually frowned upon. Having said that, it is not an
absolute rule and I have found myself having to do this a few times, so I would
rather discourage the use of boolean logical operators for a totally different
reason: don’t use them because they will confuse readers of your code.
Can someone come up with a convincing use for a boolean logical operator?
#1 by Damien B on December 27, 2005 - 8:19 am
I use them when I have to reproduce in code the result of an analysis made from a Karnaugh map, and I use them only with previously calculated boolean variables. The final expression is very compact and not easy to read, but it’s not meant to be read without the map. The use of ‘&’ or ‘|’ in that case is still more readable than using ‘&&’ or ‘||’, because the boolean variable are named with a single character, and it’s not good when the operator is longer than the variable. Plus, it acts as a strong signal for the reader that the complexity of the expression lies more in boolean algebra than from the methods called.
#2 by Tom Hawtin on December 27, 2005 - 10:15 am
&= and |= are probably used more often than & and |.
In certain simple contexts, & and | may run faster than && and ||.
#3 by Alex Blewitt on December 27, 2005 - 10:27 am
You can also have:
boolean test = (a ? b : false);
if you want to be really vague for your ‘and’ operators. In this case, the second argument (b) is only evaluated once if the first test (a) is true. A similar expression holds for ‘or’.
#4 by Anonymous on December 27, 2005 - 4:07 pm
I used this construct for the semantic document validation. Assume there are 3 independent checks to be made. If the first validation fails and the failure is not fatal, you want to continue with the validation and to send a reply enumerating ALL errors at once. The validation check should be: isValid = checkA() & checkB & checkC(). Short-circuiting is not appropriate. Or, you can use a loop if the number od checks is not fixed.
#5 by Rodrigo Kumpera on December 28, 2005 - 8:47 am
The bitwise operators should be a lot faster than the logical ones when the left side expression is very simple.
This is true today, but not a decade ago, and it’s a matter of knowing how a CPU works. Modern CPUs have very deep pipelines, so branches have a very hight cost, this was not the case for the 80386.
Given “a() && b()” x “a() & b()” the result should be something like:
“a() && b()”
invoke a()
if false branch to “else clause”
invoke b()
if false branch to “else clause”
“a() & b()”
a = invoke a()
b = invoke b()
test a b
if false branch to “else clause”
The generated code will be about the same size, and given that the code for b() is short any branch misprediction of the first test will cause enouth stall to make the bitwise version to perform better.
As this is a peephole optimization I must say that it doesn’t justify it’s use enouth and likely others have said, the &=, |= forms are more frequent and userfull.
#6 by Ron on December 30, 2005 - 10:04 am
findbugs flags uses of &
it’s neat, but I sure don’t have a use for it.
#7 by Ajith Kallambella on January 4, 2006 - 12:02 pm
I believe the third & operator is a serendipity. It is an interesting side effect of how Java language treats boolean types. The language lacks a true boolean type, and most compilers encode them as ints( or short, byte in some cases, but all upcastable to an int). As a result, the bitwise & and | works with boolean operands.
The JVM spec says that “There are no Java virtual machine instructions solely dedicated to operations on boolean values.”.
#8 by Cameron on January 9, 2006 - 7:28 pm
> The language lacks a true boolean type
Incorrect. The Java language _does_ have a boolean type, but the JVM specification does not go out of its way to provide special support for it.
Peace.
#9 by Cameron on January 9, 2006 - 7:29 pm
– “The language lacks a true boolean type”
The Java language _does_ have a boolean type, but the JVM specification does not go out of its way to provide special support for it.
Peace.
#10 by Porek on November 19, 2006 - 11:54 am
taste of home modular home home appraisal dealer home mobile rental home electronics home buying home care foreclosure home home shopping home theater better home and garden home builder adult novelties google home diabetic Handbags home improvement new apartment home home renovation home depot canada
#11 by footmania on January 6, 2007 - 7:06 pm
The bewildered scientist struck the match in a narrow tunnel to discover the dark secret.