Leepoint Java Reference Notes on the Java language and its standard library.

Bitwise operators

Operating on individual bits. Rarer than it used to be, still occasionally exactly right.

Operator Meaning
& AND, 1 where both bits are 1
\| OR. 1 where either is 1
^ XOR, 1 where exactly one is 1
~ NOT, flips every bit
<< left shift
>> arithmetic right shift, keeps the sign
>>> logical right shift, fills with zero

They work on integral types. Operands narrower than int are promoted to int first, which is why byte b = ~b; will not compile without a cast.

Flags

The main everyday use. Give each option a bit:

static final int READ    = 1;      // 0001
static final int WRITE   = 1 << 1; // 0010
static final int EXECUTE = 1 << 2; // 0100

int perms = READ | WRITE;                  // set
boolean canWrite = (perms & WRITE) != 0;   // test
perms |= EXECUTE;                          // add
perms &= ~WRITE;                           // remove
perms ^= READ;                             // toggle

Note != 0 on the test. perms & WRITE yields 2, not 1, so comparing to 1 fails. Comparing against the flag itself also works: (perms & WRITE) == WRITE.

In modern code an EnumSet is usually clearer and just as fast. Bit flags remain right when the value crosses a boundary you do not control, a file format, a protocol, a native API.

Shifts

x << n multiplies by 2ⁿ; x >> n divides by 2ⁿ, rounding toward negative infinity. Do not write shifts for arithmetic: the compiler optimises * 2 perfectly well and << 1 only obscures the intent.

The difference between >> and >>> matters for negative numbers. -8 >> 1 is -4, sign preserved. -8 >>> 1 is 2147483644, because the sign bit is filled with zero. Use >>> when the value is a bit pattern rather than a number.

Shift counts are taken modulo 32 for int and 64 for long, so x << 32 is x, not zero. This surprises people.

& and && are different

& and | on booleans work, but always evaluate both sides. && and || short-circuit. That matters when the right side would throw:

if (s != null && s.length() > 0)   // safe
if (s != null &  s.length() > 0)   // throws on null

Use the doubled forms for logic. The single ones are for bits.

Useful idioms

(n & 1) == 0            // even
n & (n - 1)             // clears the lowest set bit; zero means power of two
Integer.bitCount(n)     // count the set bits
Integer.toBinaryString(n)