Java Bitwise Operators

In this tutorial we will look at Java Bitwise operators and how they work.

Java Bitwise operators are used to perform manipulations of the bits of binary values. Bitwise operators can be used with Java data types such as: byte, short, char, int, long.

Bitwise operators manipulate the bits of a value and they perform bit-by-bit operations. A bitwise operation requires the operand(s) of the operation to be in binary format (bytes), and applies the operation one bit at a time. If you remember a byte is 8 bits, where a bit can have a value of 0 or 1.

When performing a bitwise operator the operands are first converted into their binary representation. The operator is then applied to each binary value in order to perform the calculation. After the calculation is finished the result is converted back to its decimal representation.

Bitwise Operator Performance

As mentioned bitwise and bit shift operators are powerful techniques that manipulate the bits of a binary value. These operations are among the fastest in Java but many programmers are not familiar with them. If you have a C or C++ programming background you are likely familiar with the bitwise operations. For example the MFC framework provided by Microsoft to create a Windows Graphical User Interface uses bitwise operators to turn on and off features of a user interface.

Bitwise Operator Basics

Before looking at these operations in Java, lets recap on the binary format. If we recall a byte is 8 bits and a bit has a value of 1 or 0. We can also consider 0 as False and 1 as True. Given two values in binary we can preform binary operations on these values. Such operations include AND, OR, NOT, XOR etc.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Binary Arithmetic
0 + 0 = 0
0 + 1 = 1
1 + 1 = 10

Negation
~0 = 1
~1 = 0

OR
0 | 0 = 0
1 | 1 = 1
0 | 1 = 1
1 | 0 = 1

XOR
0 ^ 0 = 0
1 ^ 1 = 0
0 ^ 1 = 1
1 ^ 0 = 1

And
0 & 0 = 0
1 & 1 = 1
0 & 1 = 0
1 & 0 = 0

Java provides several bitwise operators these include: ~ for complement (negation), | for bitwise OR, ^ for XOR operation, and & for And operation.

Bitwise Logical Operators

The bitwise logical operators are AND(&), OR(|), XOR(^), and NOT(~).

Bitwise OR (|)

The bitwise or operator is invoked with the | symbol. The bitwise OR operator compares each binary digit of two binary values and returns 1, if either of them is 1.

Let’s look at an example of the Bitwise Or Operator:

1
2
3
4
5
6
7
@Test
public void bitwiseOr() {
    int a = 2; //0010
    int b = 4; //0100
    int result = a | b;
    assertEquals(6, result);
}

The result of the above bitwise or operation is 6 because if we remember this operation returns 1 if at least one bit in the two operands is one.

1
2
3
4
  0010
+ 0100
---------
  0110

Above we see that if both bits are 0 the result is 0, alternatively, if at least one of the bits is 1 the result is 1. In the above example after the calculation is performed the result is 0110 which is the binary equivalent of 6.

The or bitwise operator in a way is equivalent to the Java || or logical operator when working with boolean values. When at least one of the boolean values is true the result is true otherwise false.

Bitwise AND (&)

The bitwise and operator is invoked using the & symbol. The AND operator compares each binary digit of two binary values and returns 1 if both are 1, otherwise it returns 0.

For example:

1
2
3
4
5
6
7
@Test
public void bitwiseAnd_equalsZero() {
    int a = 2; //0010
    int b = 4; //0100
    int result = a & b;
    assertEquals(0, result);
}

The result of the above operation is 0, because if we remember from the previous examples the and operation returns 1 only if both operands are 1

1
2
3
4
  0010
+ 0100
---------
  0000

Lets look at another example

1
2
3
4
5
6
7
@Test
public void bitwiseAnd() {
    int c = 6;
    int d = 5;
    int result = c & d;
    assertEquals(4, result);
}
1
2
3
4
  0110
+ 0101
----------
  0100

The binary value of 0100 is equivalent to the value 4. The and bitwise operator in a way is equivalent to the Java && logical operator when working with boolean values. When two boolean values are true the result is true otherwise false.

Bitwise XOR (^)

The bitwise xor operator is invoked with the ^ symbol. The XOR operator again compares the bits of a binary value and returns 0 if both of the bits are 1 or 0.

The XOR operator compares each binary digit of two values and gives back 1 if both the compared bits are different. This means that if the bits of both the values are 1 or 0 the result will be 0, otherwise, the result will be 1.

1
2
3
4
5
6
7
@Test
public void bitwiseXOR() {
    int a = 2; //0010
    int b = 2; //0010
    int result = a ^ b;
    assertEquals(0, result);
}
1
2
3
4
  0010
+ 0010
---------
  0000

In the above example the result 0000 is equivalent to 0 because none of the bits in each of the binary values have alternating bits.

Lets look at another example of the XOR operation:

1
2
3
4
5
6
7
@Test
public void bitwiseXOR_exampleTwo() {
    int a = 2; //0010
    int b = 4; //0100
    int result = a ^ b;
    assertEquals(6, result);
}
1
2
3
4
   0010
+  0100
---------
   0110

In the above example the result is 0110 which is equivalent to the value 6.

Bitwise COMPLEMENT (~)

The bitwise complement operator is invoked with the ~ symbol. The bitwise complement operator is simply the negation of each bit in the binary value. In this case the bitwise complement operator inverts the value of each bit.

1
2
3
4
5
6
@Test
public void bitwiseComplement() {
    int number = 3; //0011
    int result = ~number;
    assertEquals(-4, result);
}

The result above is the binary value 1100 which is equivalent to the value -4 because each bit in the pattern was inverted.

Bitwise Operator Table

Below we summarize each of the bitwise operators we looked at in the previous sections. The bitwise operators are applied to the values a and b in the below table.

1
2
3
4
5
A  B  A&B  A|B  A^B  ~A  ~B
0  0  0    0    0     1   1
1  0  0    1    1     0   1
0  1  0    1    1     1   0
1  1  1    1    0     0   0 

Bitwise Shift Operators

Binary shift operators manipulate the bits of a binary value by shifting the bits of the value to the left in the case of the left shift operator and to the right with the right shift operator.

The bit shifting operation is a binary operation that takes the value to shift as its left operand and the number of times to shift as its right operand.

1
value <operator> <number_of_times>

Signed Left Shift <<

The bitwise signed left shift operator is invoked with the << symbol. The left shift operator shifts the bits to the left by the number of times specified in its right operand.

Moreover, the left shift operator fills the space created on the right with 0 after shifting the bits to the left.

1
2
3
4
5
6
@Test
public void bitwiseLeftShift() {
    int number = 10; //1010
    int result = 10 << 2; //101000
    assertEquals(40, result);
}

In the above code we shift the integer 10 with a binary value of 1010, 2 places to the left. This creates the new binary value shown below:

1
1010101000

When we left shift the value above to the left by 2 places the operation adds two zeros to the right of the binary value. Moreover, it is important to note that shifting a number by 1 is equivalent to multiplying it by 2. So shifting a value by n positions is equal to 2 ^ n.

Signed Right Shift >>

The bitwise signed right shift operator is invoked with the >> symbol. The right shift operator is the opposite of the left shift operator. However, the value used to fill the left side is dependent on the value to be shifted.

  • if it is negative, the leftmost bit being 1, the empty places are filled with 1.
  • if it is positive, the leftmost bit being 0, the empty places are filled with 0.
1
2
3
4
5
6
@Test
public void bitwiseRightShift_positiveValue() {
    int number = 10; //00001010
    int result = number >> 2; //00000010
    assertEquals(2, result);
}

Above we shift the number 10 two places to the right. Since the binary value of the number 10, 00001010 starts with a zero the empty space to the left is filled with two zeros, thus creating the binary value 00000010 which is equivalent to the number 2.

Lets also look at an example of shifting a negative value.

1
2
3
4
5
6
@Test
public void bitwiseRightShift_negativeValue() {
    int number = -10; //-1010
    int result = number >> 2;
    assertEquals(-3, result);
}

In the above example the binary value is shifted to the right by 2 places, filling the space to the left with ones.

Unsigned Right Shift >>>

The bitwise unsigned right shift operator is invoked with the >>> symbol. This operator is similar to the signed right shift operator.

However, the unsigned right shift operator differs in that the empty space to the left is filled with 0 regardless if the value being shifted is positive or negative. Hence, the result of this operation will be positive.

1
2
3
4
5
6
@Test
public void bitwiseUnsignedRightShift() {
    int number = -10; //-1010
    int result = number >>> 2;
    assertEquals(1073741821, result);
}

Bitwise Versus Logical Operators

In previous sections we referenced Java logical operators when comparing certain bitwise operators. However, it is important to expand on the differences between Java bitwise and logical operators.

The main difference is that logical operators work with boolean expressions that return either a true or false value. While, bitwise operators operate on binary values manipulating their bits.

Moreover, bitwise operators that take two operands always evaluate both, whereas logical operators can perform short circuit evaluation, in that all of the values may not be evaluated.

Where Are Bitwise Operators Used

Some places where bitwise operators are used include:

  • Applications with a Gui, can use bitwise operators to evaluate what options of a GUI component should be enabled.
  • Networking protocols.
  • Data encryption.
  • Data Compression.

Conclusion

In this tutorial we explored bitwise operators in Java. We looked at the different types of operators and how they can be used. We also looked at the difference between logical and bitwise operators, and finally we looked at some use cases for using them.