skip to content

What do Java's bitwise operators &, |, ^, and ~ do, and how do they differ from the logical operators && and ||?

level: juniorimportance: must knowfreq 62%

answer

  1. & both, | either, ^ differ, ~ flip
  2. ~x == -x-1 (two's complement)
  3. &&/|| short-circuit, & / | always evaluate
  4. bitwise on ints, logical on booleans
  5. precedence trap: (x & 1) == 0

basics

~20 s

&, |, ^ compare two numbers bit by bit (AND, OR, XOR); ~ flips every bit. They work on whole numbers. && and || work on true/false, only look at the second value if needed, and give back true or false.

solid answer

~40 s

The bitwise operators act on the individual binary digits of integer types. & sets a result bit when both input bits are 1; | when either is 1; ^ (XOR) when exactly one is 1; ~ is unary and inverts every bit. They return an integer. The logical &&/|| operate on booleans, return a boolean, and short-circuit: && stops if the left side is false, || stops if the left side is true, so the right operand may never run. Note & and | also work on two booleans as non-short-circuiting logical operators (both sides always evaluated), which matters when the right side has side effects or you want to avoid branching. Use bitwise ops for flags, masks, and low-level math; use logical ops for control flow.

code

java · 10 lines
java
int a = 0b0101; // 5
int b = 0b0110; // 6
System.out.println(a & b); // 4  (both bits set)
System.out.println(a | b); // 7  (either bit set)
System.out.println(a ^ b); // 3  (bits that differ)
System.out.println(~a);    // -6 (~x == -x-1)

// precedence trap: parenthesize
boolean even = (a & 1) == 0; // correct
// boolean wrong = a & 1 == 0; // would not compile as intended

go deeper

for a junior

Knows & is AND, | is OR, ^ is XOR, ~ is NOT, and can compute a small example on paper.

for a middle

Distinguishes bitwise from logical && / ||, explains short-circuiting, and knows the precedence pitfall.

for a senior

Explains two's complement so ~x = -x-1, the int promotion of byte/short/char, and when non-short-circuiting & / | on booleans is the right choice.

for a principal

Can reason about these in performance-sensitive or branch-free code, API flag-design tradeoffs, and teaches the precedence/promotion gotchas to the team.

## What is a bit and a binary number Computers store integers in **binary**: a sequence of 0s and 1s called **bits**. A Java `int` is 32 bits wide; a `long` is 64 bits. The value 5 is `...0000 0101`, because 5 = 4 + 1 = 2^2 + 2^0. ## Bitwise operators act on each bit position independently A **bitwise operator** takes two numbers, lines up their bits column by column, and produces an output bit for each column. - **AND (`&`)** — output bit is 1 only when *both* input bits are 1. `5 & 6` = `0101 & 0110` = `0100` = 4. - **OR (`|`)** — output bit is 1 when *at least one* input bit is 1. `5 | 6` = `0101 | 0110` = `0111` = 7. - **XOR (`^`, exclusive-or)** — output bit is 1 when the two input bits *differ*. `5 ^ 6` = `0101 ^ 0110` = `0011` = 3. - **NOT (`~`)** — the only *unary* one (one operand). It flips every bit. Because Java uses **two's complement** (the standard way to represent negative numbers), `~x` always equals `-x - 1`. So `~5` = -6. The result type is `int` (or `long` if either operand is `long`); operands narrower than `int` (`byte`, `short`, `char`) are promoted to `int` first. ## Logical operators &&, || are different `&&` and `||` operate on **booleans** (`true`/`false`) and return a boolean. Their defining feature is **short-circuiting**: `a && b` does not evaluate `b` if `a` is already `false` (the answer must be false); `a || b` does not evaluate `b` if `a` is `true`. This lets you write safe guards like `if (s != null && s.length() > 0)` — the length call never runs on a null. ## The overlap: & and | on booleans Confusingly, `&` and `|` *also* accept two booleans. There they act as **non-short-circuiting** logical AND/OR: both sides are *always* evaluated. You'd choose them only when you specifically want the side effect of the right operand to always run, or to avoid a branch. `^` on two booleans means 'exactly one is true'. ## When to use which - Bitwise (`& | ^ ~`) on integers: flag sets, bit masks, hashing, parsing binary formats, fast arithmetic. - Logical (`&& ||`) on booleans: ordinary control flow and null/bounds guards. ## Common pitfall: operator precedence `&`, `^`, `|` have **lower** precedence than the comparison operators `==`, `<`, etc. So `x & 1 == 0` parses as `x & (1 == 0)` — a type error or wrong result. Always parenthesize: `(x & 1) == 0`.

  • Why does x & 1 == 0 not test whether x is even?
    Because == binds tighter than &, so it parses as x & (1 == 0), a boolean compared/anded against an int — a compile error (or wrong logic). You must write (x & 1) == 0.
  • How can XOR swap two ints without a temp variable?
    a ^= b; b ^= a; a ^= b; — each step XORs in the other value; after three steps the values are swapped. It's a curiosity, not recommended over a temp in real code.

saying these in an interview costs you the question

  • Saying & and && are interchangeable
  • Thinking ~ returns the absolute value or just negates the sign bit
  • Claiming ^ is exponentiation (it's XOR; Java has no power operator)
  • Forgetting that & / | on booleans do NOT short-circuit

context