Bit Operations in Java
No doubt Java is a strong language, with its great architecture, providing write once and run anywhere with object oriented concepts, strong multi-threading concepts, Io-streams, functional programming.
Above all those, java also provide feature to dig down in the form of bits. Its means we can also manipulate, change and quite handy in some cases.
Bit Operators
We already seen operators like ( + - / * ) which are also called mathematical operators. There are some more operators like, logical OR || , logical AND &&. But there are some more rare and likely, less-known, operators which use to manipulate bits. Every number is stored in the form bits, behind the curtain.
Those operators work on all of those numeric type primitive types.
Unary bitwise complement operator (~)
Bitwise complement will just like complement but for every bit of a number. Complement, work , like to flip, 0 to 1 and vise versa. When we apply ~ with a number, it flip each number from binary and return as a new number in decimal. As bitwise complement operator is unary so we need only one operand with it.
public static void main(String[] args) {
int value = 20;
System.out.println(value);
System.out.println(~value);
}
Result
20
-21
Let see into the example, as number is given int integer which is 32-bits and 20 in binary representation is 10100 and when we apply bitwise complement, it treats 10100 as 32-bits and will consider 28 zero in front of 10100 like
so 20 in 32-bits format will be 00000000 00000000 00000000 00010100 and when we apply bitwise complement it will be 11111111 11111111 11111111 11101011 which is -21. As you can see bitwise complement flip each bit from the binary number
Bitwise AND (&)
Bitwise AND (&) is not a unary operator, so it need two operands to perform operation. Bitwise AND (&) work same as logical AND (&&). It will work in each bit and return the resultant bit.
Let suppose we have two numbers like a=20 and b=21 and when we apply a&b it will compare each bit of 20 with its corresponding 21 bits and will send us required result in decimal.
20 in binary is 10100 and 21 in binary is 10101, now lets apply bitwise AND in 20 and 21 and we will get 10100, as first bit in both binaries are 1 so we will get, second is zero in both binaries and we get 0, third in both is 1 and we get 1, third in both is zero we get zero and last bit in both are opposite so we will get 0. so 20 & 21 we will get 20 as result because 10100 in decimal is 20.
public static void main(String[] args) {
int value = 20;
System.out.println(Integer.toBinaryString(value));
System.out.println(Integer.toBinaryString(20 & 21));
}
Result
10100
10100
Bitwise OR (|)
Bitwise OR operator is also not unary so we need two operands to perform bitwise, operation. OR works same like logical OR operator but it works, on bit level just like bitwise AND, the different is it will return 1, in the case if any of bit is 1.
领英推荐
Let's take an example, 20 in binary is 10100 and 21 is 10101 in binary, when we applied bitwise OR with those we will get 10101 value which is 21
public static void main(String[] args) {
System.out.println(20 | 21);
}
result
21
Bitwise exclusive OR (XOR) [^]
Bitwise exclusive OR is also not unary so required two operand, It will return 1 only if the bits are opposite, like 1 ^ 0 will return 1. but if bits are same it always return 0.
Let's take an example, 20 in binary is 10100 and 21 is 10101 in binary, when we applied bitwise exclusive or it will return 00001.
public static void main(String[] args) {
int value = 20;
System.out.println(value ^ 21);
}
result
1
Bit shit operators
Signed Left shift (<<)
Singed left shift two operands, it takes the bit of first operand and shift bits to left by the given number in second operand. for example if we do 20 << 1, it will shift every bit 1 to left. As we number is consider as integer (32-bits) in binary, even byte, short, char all are promoted as integer in signed left shift operator.
so 20 in binary 32-bits format is 00000000 00000000 00000000 00010100 and when we apply signed left shift operator with value 1 like 20 << 1 then we will get 00000000 00000000 00000000 00101000 which is 40 in decimal.
Let's take another example, 6 << 1 will return us 12, as 6 in binary is 110 and 6<<1 will result in 1100 which result in 12, now let's see to shift 2, as 6<<2 and we will get 11000 which is 24, as we realize from our examples that resultant is equal's to k * 2(n) where k is first operand, and n is the number need to shift left.
As max bits for a number is 32-bits in the case of char, short, byte, int and is promoted as int while using singed left shift operator, and left shift operator never throw exception so if we try to do 6<<38 then it will work in a way 6<<6 (38-32 = 6)
Right Shift Operators
There are two types of right shift operators, one is signed right shift operator, and other is unsigned right shift operators. Binary number doesn't provide any specific solution to represent negative numbers in binary format. Java use two's complement to represent negative numbers.
Signed right shift (>>) is a signed right shift which shift bits to right side by the given numbers of second operand. It also take care of negative number and preserved the sign. Negative numbers remain negative and positive numbers remain positive. Similar to left shift, the right shift of?n?positions is equivalent to division by 2^n. Or division by 2^n?-1 in case of odd numbers.
Unsigned right shift (>>>) unlike signed, unsigned is not take care of negative numbers. it shift bits to right and pad zero from the left. Using unsigned right shift we always get positive numbers.
Conclusion
Bit manipulation can be very handy sometime, and really effective. It increase performance and fast computation but there are some disadvantages of that as well. While using bit manipulation readability suffered a-lot, Even its difficult to use for those who never use it before. Only use those where the requirement is performance critical and readability is not a issue. This concept is not used for everywhere, as it damage readability, and code will not be simple and easy to modified by new developers.