You're probably familiar with the word "bit". If not, let's recall what it means :)
A bit is the smallest unit of information in a computer. Its name comes from binary digit. A bit can be expressed by one of two numbers: 1 or 0.
There is a special binary number system based on ones and zeros.
All operations are performed from left to right, taking into account their precedence.
For example, if we write
We won't delve into a mathematical jungle here. We'll only note that any number in Java can be converted into binary form. To do this, you need to use the wrapper classes.
For example, here's how you can do this for an
int
:
public class Main {
public static void main(String[] args) {
int x = 342;
System.out.println(Integer.toBinaryString(x));
}
}
Console output:
101010110
1010 10110 (I added the space to make it easier to read) is the number 342 in the decimal system. We've actually broken this number down into individual bits: zeros and ones. Operations performed on bits are called bitwise.
~
 bitwise NOT.
public class Main {
public static void main(String[] args) {
int x = 342;
System.out.println(~x);
}
}
Console output:
169
169 is our result (010101001) in the familiar, decimal system :)
&
 bitwise AND
&&
).
The &&
operator, you will recall, returns true only if both operands are true. Bitwise &
works in a similar way: it compares two numbers bit by bit. The comparison produces a third number.
For example, let's take the numbers 277 and 432:
110110000 is 277 represented as a binary number
1000101011 is 432 represented as a binary number
Next, the operator &
compares the first bit of the upper number to the first bit of the bottom number. Because this is an AND operator, the result will be 1 only if both bits are 1. In any other case, the result is 0.
100010101
&
110110000
_______________
10001000  result of the &
operator
First, we compare the first bits of the two numbers, then the second bits, then the third, and so on.
As you can see, in only two cases are both corresponding bits in the numbers equal to 1 (the first and fifth bits). All other comparisons produced 0s.
So in the end we got the number 10001000. In the decimal system, it corresponds to the number 272. Let's check:
public class Main {
public static void main(String[] args) {
System.out.println(277&432);
}
}
Console output:
272

 bitwise OR.

110110000
_______________
110110101  result of the 
operator
Here's we get a different result: the only bits that remain zeros are those bits that were zeros in both numbers.
The result is the number 110110101. In the decimal system, it corresponds to the number 437
Let's check:
public class Main {
public static void main(String[] args) {
System.out.println(277432);
}
}
Console output:
437
We calculated everything correctly! :)
^
 bitwise XOR (exclusive OR)
^
432.
But let's dig into it together one more time :)
100010101
^
110110000
_______________
010100101  result of the ^
operator
That's our result. Those bits that were the same in both numbers produce a 0 (meaning the "only one" test failed). But the bits that formed a 01 or 10 pair became ones.
Our result is the number 010100101. In the decimal system, it corresponds to the number 165.
Let's see if our calculations are correct:
public class Main {
public static void main(String[] args) {
System.out.println(277^432);
}
}
Console output:
165
Super! Everything is just as we thought :)
Now it's time to get acquainted with bit shifts operators.
The name speaks for itself. We take some number, and move its bits left or right :) Let's see how it looks:
Shift left
A shift of bits to the left is indicated by<<
Here's an example:
public class Main {
public static void main(String[] args) {
int x = 64;//value
int y = 3;// Shift distance
int z = (x << y);
System.out.println(Integer.toBinaryString(x));
System.out.println(Integer.toBinaryString(z));
}
}
In this example, the number x = 64 is called the value. It's the bits of the value that we'll shift. We'll shift the bits to the left (you could have guessed this by the direction of the <<
operator)
In the binary system, the number 64 = 1000000
The number y = 3
is called shift distance. The shift distance indicates how many bits to the right/left you want to shift the bits of the number x
In our example, we'll shift them 3 bits to the left.
To see the shift process more clearly, look at the picture.
In this example, we use int
s. Ints occupy 32 bits in the computer's memory. This is how our original number 64 looks:
And now we take each of our bits and literally shift them to the left by 3 places:
Take a look at what we got. As you can see, all our bits have shifted, and another 3 zeros have been added from the edge of the range. Three, because we shifted by 3. If we had shifted by 10, 10 zeros would have been added.
Thus, the expression
x << y
means "shift the bits of the number x
to the left by y places". The result of our expression is the number of 1000000000, which is 512 in the decimal system.
Let's check:
public class Main {
public static void main(String[] args) {
int x = 64;//value
int y = 3;// Shift distance
int z = (x << y);
System.out.println(z);
}
}
Console output:
512
Spot on!
Theoretically, the bits could be shifted endlessly, but because our number is an int
, we have only 32 binary digits available. Of these, 7 are already occupied by 64 (1000000).
Therefore, if we shifted 27 places to the left, our only one would move beyond the data type's range and be lost.
Only zeros would remain!
public class Main {
public static void main(String[] args) {
int x = 64;//value
int y = 26;// Shift distance
int z = (x << y);
System.out.println(z);
}
}
Console output:
0
As expected, the one moved beyond the 32 available bits and disappeared. We ended with a 32bit number consisting of only zeros.
Naturally, this corresponds to 0 in the decimal system.
Here's a simple rule for remembering shifts to the left:
For each shift to the left, the number is multiplied by 2.
Let's try to calculate the following expression without pictures of bits
111111111
<<
3
We need to multiply the number 111111111 by 2. As a result, we get 888888888. Let's write some code and check:
public class Main {
public static void main(String[] args) {
System.out.println(111111111 << 3);
}
}
Console output:
888888888
Shift right
This operation is denoted by>>
.
It does the same thing, but in the other direction! :)
We won't reinvent the wheel. Let's try it with the same int
64.
public class Main {
public static void main(String[] args) {
int x = 64;//value
int y = 2;// Shift distance
int z = (x >> y);
System.out.println(z);
}
}
As a result of a shift to the right by 2, the two extreme zeroes in our number move out of range and are lost. We get 10000, which corresponds to the number 16 in the decimal system
Console output:
16
Here's a simple rule for remembering shifts to the right:
Each shift to the right divides by two, discarding any remainder.
For example,
35
>>
2
means that we need to divide 35 by 2 twice, discarding the remainders
35/2 = 17 (discard remainder 1)
17/2 = 8 (discard remainder 1)
In the end, 35 >>
2 should be equal to 8.
Let's check:
public class Main {
public static void main(String[] args) {
System.out.println(35 >> 2);
}
}
Console output:
8
Operator precedence in Java
While writing and reading code, you'll often find expressions that combine several operations. It's very important to understand the order they will be executed in (otherwise, you may be surprised by the result) Because Java has lots of operations, each of them has been assigned a place in a special table:Operator Precedence
Operators  Precedence 

postfix  expr++ expr 
unary  ++expr expr +expr ~ ! 
Multiplicative  * 
additive  +  
shift  << >> >>> 
relational  < > <= >= instanceof 
equality  == != 
bitwise AND  & 
bitwise exclusive OR  ^ 
bitwise inclusive OR   
logical AND  && 
logical OR   
ternary  ? : 
assignment  = += = *= /= %= &= ^= = <<= >>= >>>=

int x = 6  4/2;
then the division operation (4/2
) will be performed first. Although it comes second, it has higher precedence.
Parentheses and brackets indicate maximum precedence. You probably remember that from school.
For example, if you add them to the expression
int x = (6  4)/2;
then the subtraction is performed first, since it is enclosed in parentheses.
The precedence of the logical &&
operator is rather low (see the table), so it will usually be last.
For example:
boolean x = 6  4/2 > 3 && 12*12 <= 119;
This expression will be executed as follows:
 4/2 = 2
boolean x = 6  2 > 3 && 12*12 <= 119;
 12*12 = 144
boolean x = 6  2 > 3 && 144 <= 119;
 62 = 4
boolean x = 4 > 3 && 144 <= 119;
Next, the comparison operators are executed:
 4 > 3 = true
boolean x = true && 144 <= 119;
 144 <= 119 = false
boolean x = true && false;
And, finally, the AND operator (&&
) will be executed last.
boolean x = true && false;
boolean x = false;
For example, the addition(+
) operator has a higher precedence than the !=
(not equal) comparison operator;
Therefore, in the expression
boolean x = 7 != 6+1;
the 6+1 operation will be performed first, then the 7 != 7 check (which evaluates to false), and finally the assignment of the result (false) to the variable x
(assignment generally has the lowest precedence of all operators; see the table).
Phew! It was a huge lesson, but you did it!
If you didn't fully understand some of this or previous lessons, don't worry. We'll touch on these topics more than once in the future.
Here are some useful relevant links:
Excellent illustrated article about bitwise operations
Numeric operators
Logical operators
A couple of CodeGym lessons about logical and numerical operations. We won't get to these any time soon, but there's no harm in you reading them now.
GO TO FULL VERSION