134

The bitwise operators are supposed to travel variables and operate on them bit by bit. In the case of integers, longs, chars this makes sense. These variables can contain the full range of values enforced by their size.

In the case of booleans, however, a boolean can contain only two values. 1 = true or 0 = false. But the size of the boolean isn't defined. It can be as big as a byte or as small a bit.

So what's the effect of using a bitwise operator on a boolean? Does the JVM essentially translate it to a normal logical operator and move on? Does it treat the boolean as a single bit entity for the purpose of the operation? Or is the result undefined along with the size of a boolean?

Daniel Bingham
  • 12,414
  • 18
  • 67
  • 93
  • 1
    I think you can't use a bitwise operator on a boolean. Only on numbers. I'm sure ~ will not work, I don't know what about other operators. – Martijn Courteaux Nov 12 '09 at 18:05
  • 4
    You can use some of them, we just discovered an | used in our legacy code. We're removing it, but this code compiled and worked. – Daniel Bingham Nov 12 '09 at 18:10
  • 9
    Since one is short-circuiting and the other isn't (see mobrule's answer), before you change the | to || you may want to make sure the subsequent boolean expressions don't have any side-effects that the original programmer intended to always execute. – John M Gant Nov 12 '09 at 18:30

4 Answers4

136

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.

fengqi
  • 367
  • 2
  • 10
Noel Ang
  • 4,989
  • 1
  • 25
  • 19
  • 71
    Specifically, & and ^ and | are the non-short-circuit logical boolean operators. – Ken Nov 12 '09 at 18:36
  • If the above is true, why is http://ideone.com/oGSF7c throwing a null pointer exception? If the `|=` operator was logical, the program should never have run the `x.getValue()` directive. – ikromm Feb 05 '15 at 12:34
  • 1
    @JohnKrommidas, your x is null, which is why you are getting a NullPointerException. You need to instantiate it. – Ben Mar 16 '15 at 21:00
  • @Ben, that's the whole point. If the operation was bitwise, the VM should never would have bothered to check the second part of the statement. Since it does check it, the operation cannot be bitwise. – ikromm Mar 18 '15 at 06:47
  • 5
    @Ben, As @Ken says, the logic is non-short-circuiting, so the second part is evaluated. So `a || x.foo()` is safe if x is null, but `a | x.foo()` is not. `|=` follows the same rules as `|`. – Michael Smith May 13 '15 at 01:28
97

Using the bitwise operator can circumvent short-circuiting behavior:

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

If booleanExpression1() evaluates to false, then
booleanExpression2() is not evaluated in the first case, and
booleanExpression2() (and whatever side-effects it may have) is evaluated in the second case,

mob
  • 117,087
  • 18
  • 149
  • 283
  • 2
    And the bitwise operation performs usually [faster than the short-circuit one](http://stackoverflow.com/a/3076091/94363) (provided the evaluation is simple) – rds Feb 24 '13 at 16:12
  • 1
    The bitwise `&` will be faster, but the call to the second function could be ignored with the use of `&&` – NatNgs Jan 11 '18 at 14:29
25

Beyond what's covered in the other answers, it's worth noting that && and || have different precedence from & and |.

Extract from the precedence table (with highest precedence at the top).

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

What this means to you?

Absolutely nothing, as long as you stick to either only & and | or only && and ||.

But, since | has higher precendence than && (as opposed to ||, which has lower precedence)​, freely mixing them could lead to unexpected behaviour.

So a && b | c && d is the same as a && (b | c) && d,
as opposed to a && b || c && d which would be (a && b) || (c && d).

To prove they're not the same, consider an extract from the truth table:

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 -|

If you want OR to have higher precedence than AND, you could use | and && together, but this is not recommended.

But you really should be putting them in brackets to clarify precedence whenever using different symbols, i.e. (a && b) || c (brackets to clarify precedence), a && b && c (no brackets needed).

Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
4

Even if it will work you shouldn't do it. Language specs define bitwise operators only when both operands are of primitive integer types or both are of boolean type. I'd say for any other case the results are not defined:

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

LeffeBrune
  • 3,441
  • 1
  • 23
  • 36
  • The question _is_ about booleans, not about primitives or a mix of primitives and booleans. – talonx Jun 14 '18 at 04:57