Java Bitwise operators

Java provides six bitwise operators (&, |, ^, ~, <<, and >>) that manipulate the individual bits of integer values directly. They are faster than arithmetic operators for certain tasks and are essential for flag management, bitmask operations, and low-level optimisation. This article covers all operators including the unsigned right shift (>>>), with practical examples.

Bitwise operators are used to perform bit manipulation of individual bits of a number. We can perform bitwise operations on any integral types such as int, char and short etc...

how it works?

Below are the bitwise operators that we can operate on bits.

  1. Bitwise OR ( | operator)
  2. Bitwise AND ( & operator)
  3. Bitwise XOR ( ^ Exclusive OR operator)
  4. Bitwise Complement ( ~ operator)
  5. Signed Right shift operator ( >> operator)
  6. Unsigned Right shift operator ( >>> operator)
  7. Left shift operator ( << operator)

Bitwise OR ( | operator)

Bitwise OR operator returns 1 if either of bits are 1 and 0 otherwise. Below table shows bitwise OR operator results on two bits X and Y.

  X     Y   Bitwise OR result
0 0 0
0 1 1
1 0 1
1 1 1

Bitwise AND ( & operator)

Bitwise AND operator returns 1 if both bits are 1 and 0 otherwise. Below table shows bitwise AND operator results on two bits X and Y.

  X     Y   Bitwise AND result
0 0 0
0 1 0
1 0 0
1 1 1

Bitwise XOR ( ^ Exclusive OR operator)

Bitwise XOR operator returns 1 if and only if one of the bit is 1 and the other bit is 0, it returns 0 otherwise. Below table shows bitwise XOR operator results on two bits X and Y.

  X     Y   Bitwise XOR result
0 0 0
0 1 1
1 0 1
1 1 0

Bitwise Complement ( ~ operator)

Bitwise Complement operator is an unary operator (meaning that you can apply on a single operand), it returns 1's complement result. This means it will reverse the input bits, if the input is 0 then it returns 1 and if the input is 1 then it returns 0.

For example, consider binary representation of number is 0 0 1 1, then applying bitwise complement operator on this will produce 1 1 0 0.

bits representation of number 3

Note: Please note that bitwise complement of any integer n is equal to - (n + 1).

For example, consider n =3, binary representation with 8 bits is 0 0 0 0 0 0 1 1, bitwise complement result will be 1 1 1 1 1 1 0 0 this is equivalent to 252, but this is also equivalent to -4, let's take a look.
=> Binary representation of 4 is 0 0 0 0 0 1 0 0, now lets compute 2's complement for this.
=> 1's complement is 1 1 1 1 1 0 1 1 (inverse above bits)
=> Now, add '1'
1 1 1 1 1 0 1 1
+1
__________________________
1 1 1 1 1 1 0 0

Signed Right shift operator ( >> operator)

Signed Right shift operator is an unary operator (meaning that you can apply on a single operand), it shifts one bit to the right and fills with original most significant bit (MSB) in all the bits that are left empty as a result, the reason it fills with most significant bit is to preserve the sign of the input number.

Example:

Say we have a variable a = 2, in binary representation it is 0 0 1 0, by applying right shift operator on this a >> 1 this returns 0 0 0 1
here is how it applied right shirt operator.

    • a = 0010
    • a >> 1
    • Shift bits to right by 1 position. So, 0 0 1 0 becomes   0 0 1.
    • Since the input is a positive number, for positive numbers most significant bit is 0. So, it fills empty bits with 0
    • Result now will become 0 0 0 1
Take a negative number a = -2, in binary representation it is 1 1 1 0, by applying right shift operator on this a >> 1 this returns 1 1 1 1. here is how it applied right shirt operator.
    • a = 1110
    • a >> 1
    • Shift bits to right by 1 position. So, 1 1 1 0 becomes  1 1 1
    • Since the input is a negative number, for negative numbers most significant bit is 1. So, it fills empty bits with 1
    • Result now will become 1 1 1 1

Unsigned Right shift operator ( >>> operator)

Unsigned Right shift operator is an unary operator (meaning that you can apply on a single operand), it shifts one bit to the right and fills with 0 bit in all the bits left empty as a result, this operation will not preserve the original sign of the input number.

Example:

Say we have a variable a = -2, in binary representation it is 1 1 1 0, by applying unsigned right shift operator on this a >>> 1 this returns 0 1 1 1 here is how it applied right shirt operator.

    • a = 1110
    • a >>> 1
    • Shift bits to right by 1 position. So, 1 1 1 0 becomes   1 1 1
    • Bits that are left blank will get filled with 0
    • Result now will become 0 1 1 1

Main difference between signed right shift operator and unsigned right shift operator is that unsigned right shift operator ignores the sign of input number after shifting bits whereas signed right shift operator does preserve the sign of input number.

Left shift operator ( << operator)

Left shift operator is an unary operator, it shifts one bit to the left and fills with 0 in all the bits left empty as a result.

Example:

Say we have a variable a = 2, in binary representation it is 0 0 1 0, by applying left shift operator on this a << 1 this returns 0 1 0 0
here is how it applied left shirt operator.

    • a = 0010
    • a << 1
    • Shift bits to left by 1 position. So, 0 0 1 0 becomes 0 1 0  
    • Then it fills the blanks with 0
    • Result now will become 0 1 0 0

Some of the usecases where left shift operator << comes handy is:

  • Powers of 2 can be generated efficiently with left shift operator. For example if you want to generate 23 we can do this 1 << 3
    The idea is, in binary representation each bit position is power of 2, for example 1 = 0001, and we are shifting right most bit 1 to the left side, by doing so we are creating a power of 2 with the position of where it shifted to.
    • If we do 1 << 1 0 0 0 1 => 0 0 1 0 = 2.
    • If we do 1 << 2 0 0 0 1 => 0 1 0 0 = 4.
    So, we can generalize 2n as 1 << n.
  • Similar to powers of 2, we can also generate multiplication by powers of 2, for example someNumber << 3, this is equivalent to someNumber * 23
  • Efficient data storage, by using individual bits represent flags or options, left shifting is used to set specific bits within an integer or a bit field.
    For example, 1 << 0 represents 0th bit as a flag or an option, or 1 << 1 represents 1st bit as a flag or an option.

Left shift operator works in the same way for positive and negavtive numbers and there is no Unsigned left shift operator in Java <<<