- Логические операторы в Java
- Оператор логического отрицания !
- Логическое И — &, а также условное И — &&
- Логическое ИЛИ — оператор |, а также условное ИЛИ — оператор ||
- XOR — логическое исключающее ИЛИ — оператор ^
- Приоритет логических операций
- Сложные логические выражения
- Поразрядные (побитовые) операторы
- Поразрядные операторы &, | и ^
- Дополнительный код
- Побитовый оператор отрицания ~

Логические операции в Java
Логические операции выполняются с помощью логических операторов. Уж простите за тавтологию, но дела обстоят именно так. Основные логические операции (в программировании и математике) можно применять к логическим аргументам (операндам), а также составлять более сложные выражения, подобно арифметическим действиям над числами. Например выражение:
(a | b) | (c < 100) & !(true) ^ (q == 5)
представляет собой сложное логическое выражение с четырьмя операндами:
(a | b)
, где а
и b
— переменные типа boolean
(c < 100)
(true)
(q == 5)
В свою очередь, простое логическое выражение (a | b)
также состоит из двух аргументов-операндов.
Логический операнд — это выражение, о котором можно сказать что оно является истинным или ложным, true или false. Говоря языком Java, логический операнд — это выражение типа boolean
или Boolean, например:
(2 < 1)
— логический операнд, его значение равно falsetrue
— логический операнд, значение которого, очевидно, trueboolean a
— тоже может быть логическим операндом, как и Boolean aint a = 2
— не является логическим операндом, это просто переменная типаint
String a = "true"
также не является логическим операндом. Это строка, текстовое значение которой —"true"
.
- Логическое отрицание, оно же
NOT
или инверсия. В Java обозначается символом “!
” перед операндом. Применяется к одному операнду. - Логическое и, оно же
AND
или конъюнкция. Обозначается символом “&
” между двумя операндами, к которым применяется. - Логическое или в Java, оно же —
OR
, оно же — дизъюнкция. В Java обозначается символом “|
” между двумя операндами. - Исключающее или,
XOR
, строгая дизъюнкция. В Java обозначается символом “^
” между двумя операндами. - В Java к логическим операторам можно отнести условное или, обозначаемое как
||
, а также условное и —&&
.
==
не принято относить к логическим.
Внимание! В Java логические операторы &
, |
и ^
применяются также к целым числам. В этом случае они работают несколько иначе и называются поразрядными (или побитовыми) логическими операторами. О них — ближе к концу статьи.
Рассмотрим таблицу с кратким описанием каждого из логических операторов Java, а ниже опишем их подробнее и приведем примеры кода.
Оператор Java | Имя | Тип | Краткое описание | Пример |
---|---|---|---|---|
! |
Логическое “не” (отрицание) | Унарный | !x означает “не x”. Возвращает true если операнд является false. Возвращает false если операнд является true. |
boolean x = true; Тогда // !x == false
|
& |
Логическое И (AND , умножение) |
Бинарный | Возвращает true если оба операнда равны true. | a = true; b = false; тогда a & b == false |
| |
Логическое ИЛИ (OR , сложение) |
Бинарный | Возвращает true если хотя бы один из операндов равен true. | a = true; b = false; тогда a | b == true |
^ |
Логическое исключающее ИЛИ (XOR ) |
Бинарный | Возвращает true, если один и только один из операндов равен true. Возвращает false, если оба операнда равны true или false. По сути, возвращает true, если операнды — разные. | a = true; b = false; тогда a ^ b == true |
&& |
Условное И (сокращённое логическое И) | Бинарный | То же самое, что и & , но если операнд, находящийся слева от & является false, данный оператор возвращает false без проверки второго операнда. |
|
|| |
Условное ИЛИ (сокращённое логическое ИЛИ) | Бинарный | То же самое, что и | , но если оператор слева является true, оператор возвращает true без проверки второго операнда. |
Оператор логического отрицания !
Этот оператор — унарный, то есть он применяется к одному булевскому выражению или операнду. Понять его очень просто, как и любое отрицание: оператор просто меняет значение выражения на противоположное. Таблица истинности или результаты выполнения операции отрицания:Значение a | !a |
false | true |
true | false |
public class Solution {
public static void main(String[] args) {
boolean a = true;
System.out.println(!a); // здесь наше логическое выражение меняет значение на противоположное
System.out.println(!false); // выражение не-false, как можно догадаться, будет равно... чему?
System.out.println(!(2 < 5)); // выражение (2 < 5) истинно, значит, его отрицание - ложно
}
}
Вывод программы будет следующий:
false
true
false
Логическое И — &, а также условное И — &&
Логическое И или конъюнкцию применяют к двум выражениям, и результат его действия будет истинным (true) только если оба операнда истинны. То есть, если один из операндовa
или b
равен false, то выражение a & b
будет false независимо от значения второго оператора.
Если представить, что true — это число 1, а false — 0, то оператор &
работает точно так же, как обычное умножение. Поэтому логическое И часто называют “логическим умножением”. И, кстати, этот факт помогает быстрее запомнить работу оператора &
и не путать его с оператором логического или |
.
Таблица истинности И, она же — результат работы оператора &
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); // если мы умножим правду на ложь, то определённо получим ложь
System.out.println(a & c); // правда на правду будет правда
System.out.println(false & (2 > 5));
System.out.println((2 < 5) & false);
// независимо от правдивости выражения в скобках, в таком случае нам приходится довольствоваться ложью
}
}
Результат работы программы:
false
true
false
false
Оператор &&
иногда называют “сокращённым И”. Он выдаёт такой же результат при работе с логическими операндами, что и оператор &
. Однако есть разница в самой его работе. Так, вы уже успели заметить, что если в выражении (a & b
) операнд a
равен false, то не имеет смысла проверять значение операнда b
: результат операции точно будет false. Так что если нам принципиально не нужно значение второго операнда, с помощью &&
мы сокращаем количество вычислений в программе. Если мы заменим в примере все операторы &
на &&
, результат работы будет точно таким же, но сама программа будет работать чуточку быстрее (правда, мы этого не заметим, так как речь идёт о мили-микро… короче говоря, об очень маленьких единицах времени).
Логическое ИЛИ — оператор |, а также условное ИЛИ — оператор ||
Оператор ИЛИ в Java обозначается символом|
. Логическое ИЛИ или дизъюнкцию применяют к двум выражениям, и результат его действия будет ложным (false) тогда и только тогда, когда оба операнда ложны. Здесь мы в какой-то мере наблюдаем ту же картину, что и в случае с оператором &
, но с точностью до наоборот. То есть, если хотя бы один операнд равен true, то выражение a | b
гарантированно будет true независимо от значения второго оператора.
Если &
ведёт себя как логическое умножение, то ИЛИ — это логическое сложение, если представить, что true — это 1, а false — 0. Только следует помнить, что логическое сложение работает не так, как обычное. 1 + 1 в данном случае равно не 2, а 1 (числа 2 в этой системе просто не существует). Иногда дизъюнкцию понимают как максимум из 0 и 1, и в таком случае если хотя бы один операнд равен 1 (true), мы получим именно true.
Таблица истинности ИЛИ, она же — результат работы оператора |
:
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); // Скомпонуем использование двух логических операторов: a == true, значит, !a, как мы уже знаем - это false.
System.out.println(a | c);
System.out.println((2 < 5) | false); // выражение (2 < 5) истинно, значит, при любом втором операнде мы получим получим истинный результат
System.out.println((2 > 5) | true);
}
}
Результат:
false
true
true
true
Если мы применим оператор условного ИЛИ — ||
вместо |
, мы получим ровно тот же результат, но, как и в случае с условным И &&
, он будет действовать экономно: если мы “нарываемся” на первый операнд равный true, значение второго операнда не проверяется, а сразу выдаётся результат true.
XOR Java — логическое исключающее ИЛИ — оператор ^
XOR
, сложение по модулю 2, логическое исключающее ИЛИ, логическое вычитание, строгая дизъюнкция, поразрядное дополнение… у оператора ^
есть много имён в булевой алгебре. Результат применения этого оператора к двум операндам будет равен true, если операнды разные и false, если операнды одинаковые. Поэтому его удобно сравнивать с вычитанием нулей (false) и единиц (true).
Таблица истинности XOR
, она же — результат работы оператора ^
:
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); // Скомпонуем использование двух логических операторов: a == true, значит, !a, как мы уже знаем - это false.
System.out.println(a ^ c);
System.out.println((2 < 5) ^ false);
System.out.println((2 > 5) ^ true);
}
}
Результат:
false
false
true
true
Приоритет логических операций
Как и в математике, в программировании у операторов есть определённый порядок выполнения, если они встречаются в одном выражении. Унарные операторы имеют преимущества над бинарными, а умножение (даже логическое) над сложением. Мы расположили логические операторы в списке тем выше, чем выше их приоритет:!
&
^
|
&&
||
&
и |
) имеют разный приоритет:
public class Solution {
public static void main(String[] args) {
boolean a = true, b = true, c = false;
System.out.println(a | b & c);
}
Если бы мы действовали слева направо, то есть сначала применили бы оператор |
, а затем — &
, мы бы получили значение false.
Но на деле, если вы запустите данную программу на выполнение, то убедитесь, что вывод будет true, поскольку у оператора логического И &
приоритет будет выше, нежели у оператора логического ИЛИ |
. Чтобы не путаться, нужно помнить, что &
ведёт себя как умножение, а |
— как сложение. Поменять порядок приоритета, можно. Просто примените скобки, прямо как в школьной математике. Изменим немного код нашего примера:
public class Solution {
public static void main(String[] args) {
boolean a = true, b = true, c = false;
System.out.println((a|b)&c);
}
Что тут? Сначала применяем логическое сложение в скобках, а затем уже умножение. Результатом будет false.
Сложные логические выражения
Разумеется, мы можем комбинировать логические выражения и операторы. Вспомним выражение из начала статьи:
(a | b) | (c < 100) & !(true) ^ (q == 5)
Теперь оно выглядит не так страшно. Напишем программу, которая выводит его значение, предварительно определив значения a
, b
, с
и q
.
Пример вычисления значения сложного логического выражения
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));
}
}
Обратите внимание: переменная q
у нас относится к типу int
, а вот q == 5
— это булево выражение, и оно равно false, поскольку выше мы проинициализировали q
числом 2. То же самое и с переменной c
. Это число равное 25, а вот (c < 100) — булево выражение, равное true.
Результат работы этой программы:
true
Сложные логические выражения можно применять для проверки очень запутанных и ветвистых условий, однако не стоит ими злоупотреблять: они затрудняют чтение кода.
Поразрядные (побитовые) операторы
В начале статьи мы упомянули, что операторы&
, |
и ^
можно употреблять по отношению к целочисленным типам Java. В таком случае они являются поразрядными операторами. Их также называют побитовыми, поскольку один разряд — это и есть один бит, а эти операции работают именно с битами.
Разумеется, работают они несколько иначе, нежели логические операторы, и чтобы понимать, как именно, нужно знать, что такое двоичная (бинарная) система счисления. Если вы ничего о ней не знаете или совсем забыли, предлагаем для начала ознакомиться со статьёй Java: биты и байты, а всем остальным напомним, что в двоичной системе счисления есть всего две цифры — 0 и 1, и все данные в компьютере представлены именно с помощью условных нуликов и единичек.
Любое из привычных нам чисел (десятичных; для них есть 10 разных цифр от 0 до 9, с помощью которых мы записываем любые числа) представимо в двоичной системе счисления. Перевести десятичное число в двоичное можно с помощью последовательного деления в столбик на основу системы счисления (2). Остатки от деления на каждом шагу, записанные в обратном порядке, и дадут нам искомое двоичное число. Вот, например, перевод десятичного числа 103 в двоичное представление:

Двоичная система счисления в курсе JavaRush В курсе JavaRush о двоичной системе счисления рассказывают во время изучения квеста MultiThreading (10 уровень, 1 лекция), после лекции есть несколько задач на закрепление. Однако эта тема совсем не сложная, и даже если вы ещё не прошли по курсу так далеко, скорее всего, вы в ней разберётесь. |
&
, |
и ^
в Java также используются поразрядные операторы:
-
~
поразрядный оператор отрицания >>
побитовый сдвиг вправо>>>
беззнаковый побитовый сдвиг вправо<<
побитовый сдвиг влево
Поразрядные операторы &, | и ^
Давайте рассмотрим на примере, как работают эти операторы. Допустим у нас есть два целых числа:
int a = 25;
int b = 112;
Нам нужно применить к ним три операции &
, |
и ^
и вывести на экран результат. Вот код программы:
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);
}
}
Результат работы программы следующий:
a & b = 16
a | b = 121
a ^ b = 105
Если не понимать, что происходит, то результат выглядит весьма и весьма загадочным. На самом деле, всё проще, чем кажется. Поразрядные операторы “видят” числа-операнды в их двоичной форме. И затем применяют логические операторы &
, |
или ^
к соответствующим друг другу разрядам (битам) обоих чисел. Так, для &
последний бит двоичного представления числа 25 логически складывается с последним битом двоичного представления числа 112, предпоследний — с предпоследним, и так далее:

|
и ^
.

Побитовый сдвиг влево или вправо
В Java существует несколько операторов побитового сдвига. Чаще всего используют операторы<<
и >>
. Они сдвигают двоичное представление числа соответственно влево или вправо, причём в случае сдвига вправо — с сохранением знака (что значит сохранение знака, расскажем чуть ниже). Есть ещё один оператор сдвига вправо >>>
. Он делает то же самое, что и >>
но знак не сохраняет.
Итак, рассмотрим их работу на примере.
int a = 13
a << 1
смещает все биты двоичного представления числа a влево на 1 бит.
Для упрощения представим число 13 в двоичном виде как 0000 1101. На самом деле это число выглядит так:
00000000 00000000 00000000 00001101, поскольку под числа типа int
Java выделяет 4 байта или 32 бита. Однако в примере это роли не играет, так что в этом примере будем мнить наше число однобайтовым.

a << 2
смещает все биты двоичного представления числа a
влево на 2 бита, и освободившиеся справа два бита заполняются нулями. В результате мы получим число 52.
a << 3
выдаст результат 104…
Заметили закономерность? Побитовый сдвиг a
влево на n позиций работает как умножение числа a
на 2 в степени n.
Это же касается и отрицательных чисел. Так -13 << 3
выдаст результат -104.
a >> n
смещает двоичное представление число на n позиций вправо. Например, 13 >> 1
Превращает число 1101 в число 0110, то есть, 6. А 13 >> 2
даст в результате 3.
То есть по сути, тут мы делим число на 2 в степени n, где n — количество сдвигов вправо, но с одним нюансом: если число нечётное, мы при этой операции как бы обнуляем последний бит числа. А вот с отрицательными дело обстоит несколько иначе.
Скажем, попробуйте проверить, что выдаст программа, если вы попросите её выполнить операцию -13 >> 1
. Вы увидите число -7, а не -6, как можно было бы подумать. Так происходит из-за особенностей хранения отрицательных чисел в Java и других языках программирования. Они хранятся в так называемом дополнительном коде. При этом старший разряд (тот, что слева) отдаётся под знак. В случае с отрицательным числом старший разряд равен 1.
Дополнительный код
Рассмотрим числоint a = 13
.
Если в программе вы выведем его двоичное представление в консоль помощью команды System.out.println(Integer.toBinaryString(a));
, то мы получим 1101. На самом деле это — сокращённая запись, поскольку число типа int
занимает в памяти 4 байта, поэтому компьютер “видит” его, скорее так:
00000000 00000000 00000000 00001101
Старший разряд равен нулю, значит, перед нами положительное число. Для перевода в дополнительный код:
Записываем число -13 в так называемом “прямом коде”. Для этого меняем старший разряд числа на 1.
Результат действия:10000000 0000000 0000000 00001101
Далее инвертируем все разряды (меняем 0 на 1, а 1 на 0) кроме знакового разряда. Его, по сути, мы уже поменяли.
Результат действия:11111111 11111111 11111111 11110010
(да, шаги 1 и 2 можно было бы совместить, но лучше представлять именно так)
- Прибавляем к получившемуся числу 1.
Результат действия:11111111 11111111 11111111 11110011
-13 >> 1
. Поскольку наш оператор >>
сохраняет знак, то в этой операции все освободившиеся слева биты заполняются не нулями, а единицами. Таким образом сдвигая число
11111111 11111111 11111111 11110011
на один бит вправо, в результате мы получим следующую последовательность бит:
11111111 11111111 11111111 11111001
Если перевести это число в прямой код (то есть сначала отнять 1, затем инвертировать все биты, кроме первого) мы получим число:
10000000 00000000 00000000 00000111
или -7.
Теперь, когда мы разобрались с оператором сдвига вправо с сохранением знака, станет понятно, в чем его отличие от оператора >>>
.
a >>> n
— эта операция является беззнаковым сдвигом, то есть она сдвигает двоичное представление числа a
вправо на n разрядов, но освободившиеся слева n разрядов заполняет не единицами, как оператор >>
, а нулями.
Проделаем операцию -13 >>> 1
. У нас уже есть число -13
в дополнительном коде:
11111111 11111111 11111111 11110011
При сдвиге вправо на 1 бит и заполнении освободившийся бит нулём мы получаем следующее число:
01111111 11111111 11111111 11111001
Что в десятичном представлении даёт число 2147483641
.
Побитовый оператор отрицания ~
Этот унарный оператор работает очень просто: он меняет каждый бит бинарного представления целого числа на противоположный. Возьмем число-13
:
11111111 11111111 11111111 11110011
Операция побитового отрицания ~13
просто изменит значение каждого бита на противоположное. В результате мы получим:
00000000 00000000 00000000 00001100
Или 12
в десятичном виде.
Краткие выводы
- Все логические операторы применяются к булевским выражениям, то есть таким, о которых можно сказать, true они или false.
- Если операторы
&
,|
или^
применяются к числам, речь идёт уже не о логических операциях, а о побитовых. То есть оба числа переводятся в двоичную систему и к этим числам побитово применяют операции логического сложения, умножения или вычитания. - В математической логике операторам
&
и|
соответствуют конъюнкция и дизъюнкция. - Логическое И похоже на умножения 1 (true) и 0 (false).
- Логическое ИЛИ напоминает поиск максимума среди 1 (true) и 0 (false).
- Для побитового отрицания целого числа a используется операция
~a
. - Для логического отрицания булевского выражения a используется операция
!a
. - Отрицательные числа хранятся и обрабатываются в дополнительном коде.
- Поразрядный сдвиг вправо может сохранять знак (
>>
), а может — не сохранять (>>>
).
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ