Bitwise Operators in Java

Java provides a number of bitwise operators. They can be applied to integer types including char type. They are named bitwise because they act on individual bits of their operands.


For example purpose, assume three integer variables X, Y and Z hold value 45, 25 and -35 respectively.
OperatorOperator NameTypeExample
~bitwise NOTunary~X = -46
&bitwise ANDbinaryX & Y = 9
|bitwise ORbinaryX | Y = 61
^bitwise XORbinaryX ^ Y = 52
<<Left ShiftbinaryX << 2 = 180,
Z << 2 = -140
>>Right ShiftbinaryX >> 2 = 11,
Z >> 2 = -9
>>>Unsigned Right ShiftbinaryX >>> 2 = 11,
Z >>> 2 = 1073741815
Since X, Y and Z are integer types, they are each 4 byte(32 bits) wide. 
VariableValuebit-pattern
X4500000000 00000000 00000000 00101101
Y2500000000 00000000 00000000 00011001
Z-3511111111 11111111 11111111 11011101

Note that all the binary bitwise operators have compound assignment forms which are just shortcuts and slightly optimised version of their normal forms.
OperatorUseEquivalent to
&=X &= YX = X & Y
|=X |= YX = X | Y
^=X ^= YX = X ^ Y
<<=X <<= YX = X << Y
>>=X >>= YX = X >> Y
>>>=X >>>= YX = X >>> Y

The Bitwise Logical Operators

There are 4 bitwise logical operators: &, |, ^ and ~ . The Table below shows the bitwise operations for individual bits.

XYX & YX | YX ^ Y~X
000001
010111
100110
111100

This table for bitwise logical operators can be easily extended to numbers(so that operation happens on multiple bits).

Bitwise NOT

It is a unary operator meaning it takes only one operand. It inverts all the bits of its operand i.e. 0 becomes 1 and 1 becomes 0. For example: when X=45 then ~X = -46.

~ 00000000 00000000 00000000 00101101


   11111111 11111111 11111111 11010010

It is also called bitwise complement operator.

Bitwise AND

It is a binary operator meaning it takes two operands. Whenever both the operands are 1, output is 1, else 0. For example: if X=45 and Y=25 then X&Y = 9.

00000000 00000000 00000000 00101101

&

00000000 00000000 00000000 00011001


00000000 00000000 00000000 00001001

Bitwise OR

It is also a binary operator. Whenever any of  the operands is 1, the output is 1, else 0. For example: if X=45 and Y=25 then X|Y = 61.

00000000 00000000 00000000 00101101

|

00000000 00000000 00000000 00011001


00000000 00000000 00000000 00111101

Bitwise XOR / Exclusive-OR

It is yet another binary operator. Whenever exactly one of  the operands is 1, the output is 1, else 0. For example: if X=45 and Y=25 then X^Y = 52.

00000000 00000000 00000000 00101101

^

00000000 00000000 00000000 00011001


00000000 00000000 00000000 00110100

The output is:

 


The Left Shift

This operator shifts all the bits of an operand to left by specified number of times. It has the general form:

 operand << num

where the operand is left-shifted by specified number num. For a left shift by 1, the left-most bit is lost and a 0 is attached to right-most bit position. For example, if X=45, then X<<1 = 90

X = 00000000 00000000 00000000 00101101

X << 1 = 0000000 00000000 00000000 01011010

i.e all the bits were shifted left by one position, the left-most 0 falls off and a 0 appears on the right-most bit position.

 

Similarly for Y=25, Y<<3 = 200

Y = 00000000 00000000 00000000 00011001

Y << 3 = 00000000 00000000 00000000 11001000

i.e. all the bits were shifted left by 3 positions, 3 left-most bits fall off and 3 extra 0’s appear at the right.

 

This works the same way for negative numbers too. For Z = -35, Z<<2 = -140.

Z = 11111111 11111111 11111111 11011101

Z << 2 = 11111111 11111111 11111111 01110100

Here all the bits were shifted left by 2 positions, 2 left-most 1’s fall off and 2 extra 0’s are attached at the right.

 

There are two things to note here:

  1. Left-shift by n-positions is equivalent to multiplication by 2n. When X was left-shifted by 1 position it became 90 from 45 i.e. multiplied by 2, when Y was left-shifted by 3 positions it became 200 from 25 i.e. multiplied by 23 and when Z was left-shifted by 2 positions it became -140 from -35 i.e. multiplied by 22.
  2. For int type, the operand bits are lost once they shift past bit position 31, and for long type they are lost once they shift past position 63.

Be careful if you want to use left shift for multiplication by 2n, if the new number doesn’t fit into the used datatype(say int) range, the result is new number modulo datatype range.

 

Java promotes byte and short values to int in an expression. So the left-shift is performed on 4-bytes rather than 1-byte for byte and 2-bytes for short. The result of the left-shift on byte and short is also an int and they must be type-casted to suitable types.

 

It produces the output

The binary representation of b1=32 in example above is 00100000 . Inside the expression b1<<3, b1 is promoted to int and it becomes 00000000 00000000 00000000 00100000. On left-shifting by 3 positions, it becomes:00000000 00000000 00000001 00000000. When it is assigned to integer variable i1 it holds its value as 256. Since assigning an int variable to a byte variable requres explict casting, we cast it to byte type and so top 3 bytes are dropped and the bit-pattern assigned to b1 is 00000000 which has value 0.


The Right Shift

This operator shifts all the bits of an operand to right by specified number of times. It has the general form:

 operand >> num

where the operand is right-shifted by specified number num. For a right shift by 1, the right-most bit is lost and another extra bit is added at the left-most position. If the operand is positive, the bit added is 0 and if the operand is negative, the bit added is 1. There is another way to thing about it.

  • If the number was positive the left-most bit was 0, So shift the bits by specified amount and add those many 0’s to the left.
  • Similarly if the number was negative the left-most bit would have been 1, so shift the bits by specified amount and add those many 1’s to the left.

This is called sign extension and it preserves the sign of a number. i.e positive numbers remain positive and negative numbers remain negative after right-shift. That’s why >> is also called signed right-shift. (You will learn about unsigned right shift shortly)

For example, if X=45, then X>>1 = 22

X = 00000000 00000000 00000000 00101101

X >> 1 = 0000000 00000000 00000000 00010110

i.e all the bits were shifted right by one position, the right-most 1 falls off and a 0 appears on the left-most bit position since the number is positive.

 

Similarly for Y=25, Y>>3 = 3

Y = 00000000 00000000 00000000 00011001

Y >> 3 = 00000000 00000000 00000000 00000011

i.e. all the bits were shifted right by 3 positions, 3 right-most bits fall off and 3 extra 0’s appear to the left.

 

This works the same way for negative numbers too. For Z = -35, Z>>2 = -9.

Z = 11111111 11111111 11111111 11011101

Z >> 2 = 11111111 11111111 11111111 11110111

Here all the bits were shifted right by 2 positions, 2 right-most bits fall off and 2 extra 1’s are attached to the left since the number is negative.

 

One intresting thing to note is that the right-shift of -1 by any number is -1. This happens because the sign-extension keeps bringing 1’s to the left-most position leaving the bit-pattern(all 1’s) unchanged. For S = -1, S >> 5 = -1, and S >> 20 = -1.

S = 11111111 11111111 11111111 11111111

S >> 5 = 11111111 11111111 11111111 11111111

S >> 20 = 11111111 11111111 11111111 11111111

i.e. the bit-patterns don’t change at all; leaving number unchanged.


The Unsigned Right-Shift

This operator(>>>) works similar to the right shift operator (>>) but instead of filling in the higher-order bits by 0’s or 1’s depending on the sign of the number, it always fills them by 0’s. Its general form is:

operand >>> num

where the operand is right-shifted by specified number num. For a right shift by 1, the right-most bit is lost and a 0 (always) is added to left-most bit position.

 

For example, if X=45, then X >>> 1 = 22

X = 00000000 00000000 00000000 00101101

X >>> 1 = 0000000 00000000 00000000 00010110

i.e all the bits were shifted right by one position, the right-most 1 falls off and a 0 appears on the left-most bit position since the number is positive.

 

Similarly for Y=25, Y >>> 3 = 3

Y = 00000000 00000000 00000000 00011001

Y >>> 3 = 00000000 00000000 00000000 00000011

i.e. all the bits were shifted right by 3 positions, 3 right-most bits fall off and 3 extra 0’s appear to the left.

 

However, this works differently for the negative numbers. For Z = -35, Z >>> 2 = 1073741815.

Z = 11111111 11111111 11111111 11011101

Z >>> 2 = 00111111 11111111 11111111 11110111

Here all the bits were shifted right by 2 positions, 2 right-most bits fall off and 2 extra 0’s are attached to the left even if this number is negative.

This operator doesn’t care about the sign of the number on which it is applied and hence, it has the name unsigned right shift.