Understanding the bitwise operator in Java can prove helpful in numerous situations, especially when dealing with lower-level operations. There are multiple bitwise operators to consider, but they are all rather simple.
Although bitwise operators are not often necessary, it s important for you to understand them if you want to have a solid grasp of Java programming. So, let s get into it!
What are Bitwise Operators?
Bitwise operators allow a programmer to act on dataat the bit level, making it possible to extract or manipulate specific bits. You may wish to leverage this for a number of reasons, but first, let s review what bits are.
Bit Review
As you likely know, a computer operates on electrical signals, and the presence or absence of electricity is often represented asbinary, or base two. Even though most of the details are abstracted away, this principle carries over to Java.
Data is represented as a certain number of bits, or binary digits. For example, an integer in Java is 32 bits. This normally allows you to represent numbers up to 2,147,483,647 (when one bit is used as the sign bit, indicating if it is positive or negative.) For the purposes of this article, however, we will mostly use numbers that can be represented as 8 bits.
AND Operator (&)
The AND operator will perform a bitwise AND operation on two numbers. This means that for each bit in the resulting number, it will only be a 1 if both of the bits in the operands are 1 s, and a 0 otherwise. Here s an example:
int num1 = 10; // binary: 00001010 int num2 = 6; // binary: 00000110 int result = num1 & num2; |
One example where you might use the bitwiseANDoperator is when you are trying to find the parity of a number (whether it is even or odd). You can do this by AND ing it with 1. If the result is 0, then the number is even.
int number = 13; boolean isEven = (number & 1) == 0; // Result: false |
OR Operator (|)
The OR operator will perform a bitwise OR operation on two numbers. When used, for each bit in the resulting number, it will be a 1 if either bits in the operands are 1 s or if both of them are 1 s, and it s a 0 otherwise. This is also known as aninclusive OR operation. Here s an example:
int num1 = 10; // binary: 00001010 int num2 = 6; // binary: 00000110 int result = num1 | num2; |
A use for the bitwise OR operator is to combine permissions. Often in operating systems, files or processes will have permissions that define what certain users or groups are allowed to do.
Since a person can either have a permission or not have it, each one can be represented using a bit. As such, the bitwise OR operator can be used to easily combine permissions as a single number so that parsing it later is easier. Note that in Java, binary numbers can be written by prefixing them with0b. Something like this would be quite common:
int readPermission = 0b00000001; int writePermission = 0b00000010; // Combine the read and write permissions int combinedPermissions = readPermission | writePermission; // Result: 0b00000011 |
XOR Operator (^)
The XOR operator will perform a bitwise XOR operation on two numbers. For each bit in the resulting number, it will be a 1 if either of the bits in the operands are 1 s, butnotif both of them are 1 s, and it will be a 0 otherwise. Since we ignore the case in which both bits are 1 s, this is known as an exclusive OR operation. Here s an example:
int num1 = 10; // binary: 00001010 int num2 = 6; // binary: 00000110 int result = num1 ^ num2; |
XOR does have an interesting property: when you xor two numbers, let s say A and B, you can XOR the result with A to get B, and vice versa. In other words, XOR is reversible. This can be taken advantage of to easily swap two numbers without creating an extra variable. Using that property, swapping two numbers might look like:
int a = 5; int b = 3; // Swap the values of a and b |
Bitwise Complement Operator (~)
When used, the bitwise complement operator takes each bit in a number and flips it, meaning 0 s become 1 s, and 1 s become 0 s. We show the full 32 bits in this demonstration, as all of them contribute to the integer s value. Here s an example:
int num = 42; // binary: 00000000000000000000000000101010
int result = ~num; |
Left Shift Operator (
The left shift operator, as you may have guessed, shifts all the bits in a number to the left by a given number of positions. Since we are working in base 2, for every shift to the left, we are effectively multiplying the number by 2. Here s an example.
int num = 5; // binary: 00000101
int result = num // The left shift operator will shift the bits of the number to the left by the specified number of positions: |
Remember that integers in Java are always 32 bits. This means that if you want to store multiple smaller numbers within a larger integer, you can do so. For example:
int x = 3; // Binary: 00000011 int y = 5; // Binary: 00000101 // Pack x and y into a single variable |
Then, to get y back, we can bitwise AND the integer with a binary value of11111111(this is sometimes called a mask ).
int retrievedY = packed & 0b11111111; |
Read on to see how we can retrieve x.
Right Shift Operator (>>)
Similar to the left shift operator, the right shift operator shifts all the bits in a number to the right by a given number of positions. Note again that since we are working in base 2, for every shift to the right, we are halving the number.
When the right shift operator is applied, the empty spaces on the left are filled with the sign bit (first bit), which is why it is also called the signed right shift operator. Here s an example:
int num = -42; // binary: 11111111111111111111111111010110
int result = num >> 2; |
In our demonstration of using the left shift operator, we packed two numbers x and y into one integer. We know how to get y back using a mask, but we can also easily get x back with the right shift operator like so:
int retrievedX = packed >> 8; |
Unsigned Right Shift Operator (>>>)
The unsigned right shift operator works exactly the same as the normal right shift operator, except that instead of filling the empty bits on the left with the sign bit, they will always be filled with 0 s. This means when you use the unsigned right shift operator on a number, it will always be positive. Here s an example:
int num = -42; // binary: 11111111111111111111111111010110
int result = num >>> 2; |
Logical Operators vs. Bitwise Operators
When programming, you ve likely common across a statement like this:
if ([expression1] && [expression2]) { doSomething(); } |
Or
if ([expression1] || [expression2]) { doSomething(); } |
In programming, these are called logical operators. As opposed to bitwise operators, logical operators are meant to act onbooleansor expressions that evaluate to a boolean. That being said, the principle is the same. A true statement can be thought of as a 1, and 0 for a false statement.
When using logical OR (||), either or both of the expressions must be true for the
condition to pass. For logical AND (&&), both of the expressions must be true for the condition to pass. Although they are used in different ways, logical and bitwise operators are very similar at a basic level.
Wrapping Up
When used correctly, bitwise operators can save you time and allow you to write cleaner code. Although we only used integers, bitwise operators can be used on any primitive type in Java, and as such, they can be leveraged in many clever ways.
Whether you are writing low-level code or using bit manipulation tricks, bitwise operators are very useful tools. Now, let s answer some frequently asked questions.