Bit shifting treats an integer as a bit vector, moving its representation left or right. It supports compact packed values, bit flags, masks, and fast low-level arithmetic, but small Java expression details can radically change the result. section 4.12
Addition binds before shifting
Do not assume a shift binds more tightly than addition. `lo << 16 + hi` is evaluated as `lo << (16 + hi)`, not `(lo << 16) + hi`. The compiler accepts both forms, so a packing expression or handwritten `hashCode()` can silently compute an unexpected value. In a hash calculation, a late left shift can wipe out low-order bits and produce poor hash distribution, harming `HashMap` performance. section 2.1.1
Parenthesize mixed addition-and-shift expressions to state the intended grouping, then verify the arithmetic rather than merely silencing an analyzer. A buffer-capacity expression intended to add 25% can instead parse as `(BLOCK_SIZE + BLOCK_SIZE) >> 2`, yielding half the block size. Parentheses that preserve that existing parse remove the warning without repairing the intent. section 2.1.1
int value;
void applyMask(int keepBits) {
value &= (1 << keepBits) - 1;
}
This mask idiom preserves the least-significant `keepBits` bits for ordinary counts, but exposes a boundary case: shifting an `int` by 32 shifts by zero instead. section 4.12
Check these Java-specific shift hazards:
- For `int`, Java uses the shift amount modulo 32; for `long`, it uses modulo 64. Thus `1 << 32` is `1 << 0`, so `(1 << 32) - 1` becomes zero rather than an all-bits mask. section 4.12
- The shift result type follows the left operand. When constructing a `long` bit mask, a left operand written as `1` is an `int`; make the operand explicitly long when a long shift result is required. section 4.12
- Treat analyzer diagnostics as prompts to inspect intent. Tools commonly flag an `int` shifted by 32 and mixed addition/shift expressions; IDE plugins, built-in inspections, and build-integrated analyzers can surface such cases. section 1.3.2 section 2.1.1

