➗ Operators & Expressions · Beginner

Bitwise operators in Java

&, |, ^, ~ on integer bits and common bit masks.

🧩 The mysteryPack eight yes/no settings into a single number, then flip any one of them in one step. That's the magic of bitwise operators.

Numbers are bits

Every int is 32 bits, each a 0 or a 1. 12 is 1100 and 10 is 1010 (leading zeros left out). On integers, &, |, ^ and ~ are bitwise: they work on each bit position separately.

AND, OR, XOR on bits

& keeps bits set in both. | keeps bits set in either. ^ keeps bits set in exactly one.

// 12 = 1100, 10 = 1010
12 & 10   // 1000 = 8
12 | 10   // 1110 = 14
12 ^ 10   // 0110 = 6
🔮 Predict it

Your turn

6 is 110 and 3 is 011. What does this print?

System.out.println(6 & 3);
System.out.println(6 | 3);
System.out.println(6 ^ 3);
  1. 2 7 5
  2. 9 9 3
  3. 1 1 0
Show the answer

AND: 010 = 2. OR: 111 = 7. XOR: 101 = 5.

~ flips everything

~x flips all 32 bits. Because of two's complement (the way Java stores negative numbers), flipping every bit always gives -x - 1. So ~5 is -6, not -5, and ~0 is -1.

Flags and masks

Give each setting its own bit. | sets bits, & tests (or clears) them, and ^ toggles them.

int READ = 0b100, WRITE = 0b010;
int perms = READ | WRITE;   // 0b110
boolean canWrite =
    (perms & WRITE) != 0;   // true
perms = perms ^ WRITE;      // off again

Testing a flag

✗ Broken
if (perms == WRITE) { ... }

True only when WRITE is the only bit set. With READ also on, it fails.

✓ Correct
if ((perms & WRITE) != 0) { ... }

& clears every bit except WRITE. If anything is left, the flag was set.

🔮 Predict it

Your turn

What does this print?

int x = 0b1001 ^ 0b1100;
System.out.println(Integer.toBinaryString(x));
  1. 0101
  2. 101
  3. 1101
Show the answer

XOR toggles the bits that differ: 1001 ^ 1100 = 0101, which is 5. toBinaryString leaves out leading zeros, so it prints 101.

💼 In the real world

In real projects

Linux file permissions (read 4, write 2, execute 1), network packet headers, game states, and Java's own java.lang.reflect.Modifier flags all pack booleans into bits. Compact, fast, and one & answers the question.

Key takeaways

  1. & keeps bits set in both; | keeps bits set in either
  2. ^ keeps bits set in exactly one
  3. ~x == -x - 1
  4. Test a flag: (value & FLAG) != 0
🤯 Did you know?

XOR undoes itself: (a ^ k) ^ k == a for any a and k, and x ^ x is always 0. Simple ciphers and checksums are built on that trick.

Practice questions

What does this print?

System.out.println(12 & 10);
System.out.println(12 | 10);
System.out.println(12 ^ 10);
  1. 8 14 6
  2. 10 12 2
  3. 8 14 2
  4. 1 1 0
Check your answer

8 14 6. 12 is 1100 and 10 is 1010. AND gives 1000 (8), OR gives 1110 (14), XOR gives 0110 (6).

What does this print?

System.out.println(~5);
  1. -6
  2. -5
  3. 2
  4. 10
Check your answer

-6. ~ flips all 32 bits. In two's complement, ~x always equals -x - 1, so ~5 is -6.

Next: shift bits left and right. Multiply by 2 in a single step, and discover why 1 << 32 equals 1.