First of all, it's helpful to understand the
binary representation of signed integers in Java. Java uses the
two's complement method, where 0 is represented by all zero bits, and an overflow from the maximum value rolls over to the minimum value.
The binary bitwise operators &
,
|
, and
^
perform the operations AND, OR, and XOR (exclusive OR), respectively. The XOR operation is particularly interesting:
- Applying XOR to a value with the same parameter twice results in the original value. This property allows XOR to be used for simple encryption, with the argument acting as the key.
- XOR is also used to implement the XOR swap algorithm. It is a method to exchange values of variables without additional memory and without the risk of overflow. This is also a popular interview question.
The unary bitwise complement operator
~
inverts all bits of its operand. It is equivalent to XORing the argument with itself.
~x
is equivalent to
-x-1
.
~0 == -1
.
Bitwise shifts include the left shift
<<
, the signed right shift
>>
, and the unsigned right shift
>>>
. The left operand indicates what to shift, and the right operand specifies how many
bits to shift.
The second parameter, the shift distance, should not exceed the number of available bits – 31 for
int
and 63 for
long
. If a value greater than these limits is provided, only the lower 5 or 7 bits are used, respectively. Thus, for an
int
variable
x << 33
is the same as
x << 2
.
a << b
is equivalent to multiplying
a
by 2 raised to the power of
b
.
a >> b
corresponds to dividing by 2 raised to the power of
b
, rounding down. For positive
a
this is the same as
a/pow(2,b)
. For negative values
not divisible by
pow(2,b)
, this is
a/pow(2,b)-1
.
The unsigned right shift treats the number not as two's complement, but as if it were unsigned. This means that
Integer.MIN_VALUE
would be shifted as
Integer.MAX_VALUE+1
.
There is no unsigned left shift because it would be redundant and
identical to the signed shift in effect