- Logical Operators in Java
- Logical negation operator !
- Logical AND - &, as well as conditional AND - &&
- Logical OR is the operator |, as well as conditional OR is the operator ||
- XOR - logical exclusive OR - operator ^
- Priority of logical operations
- Complex logical expressions
- Bitwise (bitwise) operators
- Bitwise operators &, | and ^
- Additional code
- Bitwise negation operator ~
Logical Operations in Java
Logical operations are performed using Boolean operators. Pardon the tautology, but this is exactly how things are. Basic logical operations (in programming and mathematics) can be applied to logical arguments (operands), and can also be used to form more complex expressions, similar to arithmetic operations on numbers. For example the expression:
(a | b) | (c < 100) & !(true) ^ (q == 5)
is a complex logical expression with four operands: (a | b)
, where а
and b
are type variables boolean
(c < 100)
(true)
(q == 5)
. In turn, a simple logical expression (a | b)
also consists of two operand arguments. A logical operand is an expression that can be said to be true or false, true or false . In Java parlance, a Boolean operand is an expression of type boolean
or Boolean, for example:
(2 < 1)
— logical operand, its value is falsetrue
- a logical operand whose value is obviously trueboolean a
- can also be a logical operand, like Boolean aint a = 2
- is not a logical operand , it is just a variable of typeint
String a = "true"
is also not a logical operand . This is a string whose text value is"true"
.
- Logical negation , also known
NOT
as inversion. In Java, it is indicated by the “!
” symbol before the operand. Applies to one operand. - Logical and , it is also
AND
a conjunction. Indicated by a “&
” symbol between the two operands to which it is applied. - Logical or in Java , it is also -
OR
, it is also disjunction. In Java, it is indicated by the symbol “|
” between two operands. - Exclusive or ,
XOR
, strict disjunction. In Java, it is indicated by the symbol “^
” between two operands. - In Java, logical operators include the conditional or , denoted as
||
, as well as the conditional and -&&
.
==
is not considered a logical operator. Attention! In Java, the logical operators&
,|
and^
also apply to integers. In this case, they work slightly differently and are called bitwise (or bitwise) logical operators. About them - towards the end of the article. Let's look at a table with a brief description of each of the Java logical operators, and below we will describe them in more detail and provide code examples.
Java operator | Name | Type | Short description | Example |
---|---|---|---|---|
! |
Logical “not” (negation) | Unary | !x means “not x”. Returns true if the operand is false . Returns false if the operand is true . |
boolean x = true; Then // !x == false |
& |
Logical AND ( AND , multiplication) |
Binary | Returns true if both operands are true . | a = true; b = false; Then a & b == false |
| |
Logical OR ( OR , addition) |
Binary | Returns true if at least one of the operands is true . | a = true; b = false; Then a | b == true |
^ |
Logical exclusive OR ( XOR ) |
Binary | Returns true if one and only one of the operands is true . Returns false if both operands are true or false . Essentially, it returns true if the operands are different. | a = true; b = false; Then a ^ b == true |
&& |
Conditional AND (short logical AND) | Binary | Same as , & but if the operand to the left of & is false , this operator returns false without checking the second operand. |
|
|| |
Conditional OR (short logical OR) | Binary | Same as , | but if the operator on the left is true , the operator returns true without checking the second operand. |
Logical negation operator !
This operator is unary, meaning it applies to a single Boolean expression or operand. It is very simple to understand, like any negation: the operator simply changes the meaning of the expression to its opposite. Truth table or results of performing a negation operation:The value of a | !a |
false | true |
true | false |
public class Solution {
public static void main(String[] args) {
boolean a = true;
System.out.println(!a); // here our boolean expression reverses its value
System.out.println(!false); // non-false expression, as you might guess, will be equal to... what?
System.out.println(!(2 < 5)); // expression (2 < 5) is true, so its negation is false
}
}
The output of the program will be as follows:
false
true
false
Logical AND - &, as well as conditional AND - &&
Logical AND or conjunction is applied to two expressions, and its result will be true only if both operands are true. That is, if one of thea
or operands b
is false , then the expression a & b
will be false regardless of the value of the second operator. If you imagine that true is the number 1 and false is 0, then the operator &
works exactly the same as normal multiplication. Therefore, logical AND is often called “logical multiplication.” And, by the way, this fact helps to quickly remember the operation of the operator &
and not confuse it with the logical or operator |
. Truth table AND, it is also the result of the operator’s work&
a | b | a&b |
true | true | true |
true | false | false |
false | true | false |
false | false | false |
public class Solution {
public static void main(String[] args) {
boolean a = true;
boolean b = false;
boolean c = true;
System.out.println(a & b); // if we multiply true by false, we will definitely get false
System.out.println(a & c); // true to true will be true
System.out.println(false & (2 > 5));
System.out.println((2 < 5) & false);
// regardless of the truthfulness of the expression in brackets, in which case we have to be content with false
}
}
Result of the program:
false
true
false
false
The operator &&
is sometimes called “short AND”. It produces the same result when working with logical operands as the operator &
. However, there is a difference in his work itself. So, you have already noticed that if a & b
the operand in the expression ( ) a
is false , then it makes no sense to check the value of the operand b
: the result of the operation will definitely be false . So if we don’t fundamentally need the value of the second operand, using it &&
we reduce the number of calculations in the program. If we replace all the operators in the example &
with &&
, the result will be exactly the same, but the program itself will run a little faster (though we won’t notice this, since we are talking about mili-micro... in short, very small units of time).
Logical OR is the operator |, as well as conditional OR is the operator ||
The OR operator in Java is represented by the symbol|
. A logical OR or disjunction is applied to two expressions, and its result will be false if and only if both operands are false. Here we to some extent observe the same picture as in the case of the operator &
, but exactly the opposite. That is, if at least one operand is true , then the expression a | b
is guaranteed to be true regardless of the value of the second operator. If &
it behaves like logical multiplication, then OR is logical addition, if you imagine that true is 1 and false is 0. Just remember that logical addition works differently than normal addition. 1 + 1 in this case is equal not to 2, but to 1 (the number 2 simply does not exist in this system). Sometimes disjunction is understood as the maximum of 0 and 1, and in this case, if at least one operand is equal to 1 ( true ), we get exactly true . OR truth table, also known as the result of the operator |
:
a | b | a | b |
true | true | true |
true | false | true |
false | true | true |
false | false | false |
public class Solution {
public static void main(String[] args) {
boolean a = true;
boolean b = false;
boolean c = true;
System.out.println(!a | b); // Compose the use of two logical operators: a == true, so !a, as we already know, is false.
System.out.println(a | c);
System.out.println((2 < 5) | false); // expression (2 < 5) is true, which means that for any second operand we get a true result
System.out.println((2 > 5) | true);
}
}
Result:
false
true
true
true
If we use the conditional OR operator - ||
instead of |
, we will get exactly the same result, but, as in the case of conditional AND &&
, it will act economically: if we “run into” the first operand equal to true , the value of the second operand is not checked, but immediately the result is true .
XOR Java - logical exclusive OR - operator ^
XOR
, modulo 2 addition, logical XOR, logical subtraction, strict disjunction, bitwise complement... the operator ^
has many names in Boolean algebra. The result of applying this operator to two operands will be true if the operands are different and false if the operands are the same. Therefore, it is convenient to compare it with subtracting zeros ( false ) and ones ( true ). Truth table XOR
, also known as the result of the operator ^
:
Boolean a | Boolean b | a^b |
true | true | false |
true | false | true |
false | true | true |
false | false | false |
public class Solution {
public static void main(String[] args) {
boolean a = true;
boolean b = false;
boolean c = true;
System.out.println(!a ^ b); // Compose the use of two logical operators: a == true, so !a, as we already know, is false.
System.out.println(a ^ c);
System.out.println((2 < 5) ^ false);
System.out.println((2 > 5) ^ true);
}
}
Result:
false
false
true
true
Priority of logical operations
Just like in mathematics, in programming operators have a specific execution order when they appear in the same expression. Unary operators have advantages over binary ones, and multiplication (even logical) over addition. We have ranked logical operators higher in the list, the higher their priority:!
&
^
|
&&
||
&
and |
) have different precedence:
public class Solution {
public static void main(String[] args) {
boolean a = true, b = true, c = false;
System.out.println(a | b & c);
}
If we were to proceed from left to right, that is, to first apply the operator |
and then - &
, we would get the value false . But in fact, if you run this program, you will be sure that the output will be true , since the logical AND operator &
will have higher priority than the logical OR operator |
. To avoid confusion, you need to remember that what &
behaves like multiplication and |
what behaves like addition. You can change the priority order. Just use brackets, just like in school math. Let's change our example code a little:
public class Solution {
public static void main(String[] args) {
boolean a = true, b = true, c = false;
System.out.println((a|b)&c);
}
Whats up? First we use logical addition in brackets, and then multiplication. The result will be false .
Complex logical expressions
Of course, we can combine Boolean expressions and operators. Let's remember the expression from the beginning of the article:(a | b) | (c < 100) & !(true) ^ (q == 5)
Now it doesn't look so scary. Let's write a program that displays its value, having previously determined the values of a
, b
, с
and q
. Example of calculating the value of a complex Boolean expression
public class Solution {
public static void main(String[] args) {
boolean a = true;
boolean b = false;
int c = 25;
int q = 2;
System.out.println((a|b) | (c < 100) & !(true)^(q == 5));
}
}
Note:q
our variable is of type int
, but q == 5
this is a Boolean expression, and it is equal to false , since above we initialized with q
the number 2. The same is with the variable c
. This number is equal to 25, but (c < 100) is a Boolean expression equal to true . The result of this program:
true
Complex Boolean expressions can be used to test very complex and branchy conditions, but they should not be overused: they make the code difficult to read.
Bitwise (bitwise) operators
At the beginning of the article, we mentioned that the operators&
, |
and ^
can be used in relation to Java integer types. In this case they are bitwise operators. They are also called bitwise, since one digit is one bit, and these operations work specifically with bits. Of course, they work somewhat differently than logical operators, and to understand exactly how, you need to know what a binary number system is. If you don’t know anything about it or have completely forgotten, we suggest you first read the article Java: bits and bytes , and remind everyone else that in the binary number system there are only two digits - 0 and 1, and all data in the computer is represented precisely with using conditional zeros and ones. Any of the numbers we are used to (decimal; for them there are 10 different digits from 0 to 9, with which we write any numbers) can be represented in the binary number system. You can convert a decimal number to binary using sequential division into a column using the number system base (2). The remainders of the division at each step, written in reverse order, will give us the desired binary number. Here, for example, is the conversion of the decimal number 103 into binary representation:
Binary number system in the JavaRush course In the JavaRush course, they talk about the binary number system while studying the MultiThreading quest (level 10, lecture 1); after the lecture there are several tasks for consolidation. However, this topic is not at all difficult, and even if you haven't gotten that far in the course yet, you'll likely figure it out. |
&
, |
and ^
Java also uses bitwise operators:
~
bitwise negation operator>>
bitwise shift right>>>
unsigned bitwise right shift<<
bitwise shift left
Bitwise operators &, | and ^
Let's look at an example of how these operators work. Let's say we have two integers:int a = 25;
int b = 112;
We need to apply three operations to them &
, |
and ^
display the result on the screen. Here is the program code:
public class Solution {
public static void main(String[] args) {
int a = 25;
int b = 112;
int res1 = a & b;
int res2 = a | b;
int res3 = a ^ b;
System.out.println("a & b = " + res1);
System.out.println("a | b = " + res2);
System.out.println("a ^ b = " + res3);
}
}
The result of the program is as follows:
a & b = 16
a | b = 121
a ^ b = 105
If you don’t understand what’s happening, the result looks very, very mysterious. In fact, everything is simpler than it seems. Bitwise operators “see” the operand numbers in their binary form. And then they apply logical operators &
, |
or ^
to the corresponding digits (bits) of both numbers. So, for &
the last bit of the binary representation of the number 25 logically adds up to the last bit of the binary representation of the number 112, the penultimate bit with the penultimate one, and so on: The same logic can be traced in the case of |
and ^
.
Bit shift left or right
There are several bit shift operators in Java. The most commonly used operators<<
are and >>
. They shift the binary representation of a number to the left or right, respectively, and in the case of a shift to the right, while preserving the sign (we’ll explain what preserving the sign means below). There is another right shift operator >>>
. It does the same thing but >>
does not save the sign. So, let's look at their work using an example. int a = 13
a << 1
shifts all bits of the binary representation of the number a to the left by 1 bit. To simplify, let's imagine the number 13 in binary as 0000 1101. In fact, this number looks like this: 00000000 00000000 00000000 00001101, since Java int
allocates 4 bytes or 32 bits for numbers. However, this does not play a role in the example, so in this example we will consider our number to be one-byte. The bit vacated on the right is filled with zeros. As a result of this operation, we get the number 26. a << 2
It shifts all the bits of the binary representation of the number a
to the left by 2 bits, and the two bits vacated on the right are filled with zeros. As a result, we will get the number 52. a << 3
The result will be 104... Notice the pattern? Bitwise shifting a
left by n positions works like multiplying a number a
by 2 to the power of n. The same applies to negative numbers. This -13 << 3
will give the result -104. a >> n
shifts the binary representation of a number n positions to the right. For example, 13 >> 1
Transforms the number 1101 into the number 0110, that is, 6. And 13 >> 2
the result will be 3. That is, in essence, here we divide the number by 2 to the power of n, where n is the number of shifts to the right, but with one caveat: if the number is odd , during this operation we seem to reset the last bit of the number. But with negative ones the situation is somewhat different. Let's say, try to check what the program will produce if you ask it to perform an operation -13 >> 1
. You will see the number -7, not -6, as you might think. This happens due to the way negative numbers are stored in Java and other programming languages. They are stored in what is called complementary code. In this case, the most significant digit (the one on the left) is given under the sign. In the case of a negative number, the most significant digit is 1.
Additional code
Let's consider the numberint a = 13
. If in the program you print its binary representation to the console using the command System.out.println(Integer.toBinaryString(a));
, then we will get 1101. In fact, this is a shorthand notation, since the type number int
takes up 4 bytes in memory, so the computer “sees” it more like this:
00000000 00000000 00000000 00001101
The most significant digit is zero, which means we have a positive number. To translate into additional code:
-
We write the number -13 in the so-called “direct code”. To do this, change the most significant digit of the number to 1.
Result of the action:10000000 0000000 0000000 00001101
-
Next, we invert all the bits (we change 0 to 1, and 1 to 0) except the sign bit. In fact, we have already changed it.
Result of the action:11111111 11111111 11111111 11110010
(yes, steps 1 and 2 could be combined, but it’s better to think of it that way)
- Add 1 to the resulting number.
Result of the action:11111111 11111111 11111111 11110011
-13 >> 1
. Since our operator >>
preserves the sign, in this operation all the bits freed on the left are filled not with zeros, but with ones. Thus, shifting the number
11111111 11111111 11111111 11110011
one bit to the right, resulting in the following sequence of bits:
11111111 11111111 11111111 11111001
If we convert this number into direct code (that is, first subtract 1, then invert all bits except the first) we get the number:
10000000 00000000 00000000 00000111
or -7. Now that we have understood the sign-preserving right shift operator, it will become clear how it differs from the operator >>>
. a >>> n
— this operation is an unsigned shift, that is, it shifts the binary representation of a number a
to the right by n bits, but fills the n bits vacated on the left not with ones, like the operator >>
, but with zeros. Let's do the operation -13 >>> 1
. We already have the number -13
in two's complement:
11111111 11111111 11111111 11110011
By shifting to the right by 1 bit and filling the free bit with zero, we get the following number:
01111111 11111111 11111111 11111001
What gives the number in decimal notation 2147483641
.
Bitwise negation operator ~
This unary operator works very simply: it reverses each bit of the binary representation of an integer. Let's take the number-13
:
11111111 11111111 11111111 11110011
The bitwise negation operation ~13
will simply reverse the value of each bit. As a result we get:
00000000 00000000 00000000 00001100
Or 12
in decimal form.
Brief conclusions
- All logical operators apply to Boolean expressions, that is, those that can be said to be true or false .
- If the operators
&
,|
or^
are applied to numbers, we are no longer talking about logical operations, but about bitwise ones. That is, both numbers are converted into the binary system and the operations of logical addition, multiplication or subtraction are applied to these numbers bit by bit. - In mathematical logic, the operators
&
and|
correspond to conjunction and disjunction. - Logical AND is similar to multiplying 1 ( true ) and 0 ( false ).
- Logical OR is similar to finding the maximum among 1 ( true ) and 0 ( false ).
- For the bitwise negation of an integer a, the operator is used
~a
. - To logically negate a Boolean expression a, use the operator
!a
. - Negative numbers are stored and processed in two's complement code.
- A bitwise shift to the right may
>>
or may not preserve the sign (>>>
).
GO TO FULL VERSION