Тип Boolean и операторы сравнения в Java
Узнаём про булев тип, операции сравнения, условные конструкции if-else, switch и тернарный оператор. Осмысляем instanceof. Всё подробно и с примерами.
Boolean — это тип данных, переменные которого принимают одно из значений:
- true (истина, «да», логическая единица «1»);
- false (ложь, «нет», логический ноль «0»).
Булевы переменные в Java создают так:
Значение типа boolean возвращают операции сравнения, логические операции и их сочетания. Выражения с ними — это по сути условные высказывания, которые могут быть правдивы или нет.
Операция сравнения
В каждой операции сравнения участвуют два операнда. А выглядит она как обычное неравенство в математике. Например: a > b.
Операция сравнения возвращает:
- значение true («истина»), если высказывание с оператором правдивое (условие выполняется),
- и false («ложь») — если высказывание с оператором ложное (условие не выполняется).
Например, мы хотим сравнить в Java значения переменных a и b. Для этого используем оператор >, который возвращает булево значение (true или false).
a > b равно true, когда значение переменной a больше значения переменной b (операнд слева от > больше правого), а иначе — false.
Пример:
Оператор > сравнил операнд слева с операндом справа. Результат сравнения мы присвоили булевой переменной c.
Так как 4 > 3 (высказывание правдиво), значение переменной c после выполнения кода станет равным true.
Операторы сравнения в Java
Один оператор сравнения мы рассмотрели выше, а всего в Java их шесть:
Оператор сравнения | Обозначение в Java | Пример операции | Результат операции |
---|---|---|---|
Меньше | < | a < b | true, если операнд слева меньше правого, иначе false |
Больше | > | a > b | true, если операнд слева больше правого, иначе false |
Меньше или равно | <= | a <= b | true, если операнд слева меньше правого или они равны, иначе false |
Больше или равно | >= | a >= b | true, если операнд слева больше правого или равен ему, иначе false |
Равно | == | a == b | true, если операнд слева равен операнду справа |
Не равно | != | a != b | true, если операнд слева не равен операнду справа |
Примеры:
Где нужны значения типа Boolean
Булевы значения и условные выражения часто используются в условиях операторов ветвления, тернарного оператора и циклов.
Операторы ветвления
Оператор ветвления позволяет выбрать и исполнить определённый блок кода в зависимости от срабатывания некоторого условия.
Есть два оператора ветвления (условные конструкции): if-else и switch.
Оператор if
Его синтаксис выглядит так:
if (условие) {
//код
} else {
//код
}
В круглых скобках после if указывают условное выражение (высказывание). Если оно истинно (то есть результат его вычисления равен true), то выполняется код в фигурных скобках после условия, иначе выполняется код по ветке else (если она есть).
Примеры:
Проверяем условие в круглых скобках:
3 > 2?
Если да, то в консоль выводим: «Высказывание в скобках правдивое», иначе ничего не выводим.
Так как 3 и правда больше 2, то в консоли появилось наше сообщение.
Печатаем «Высказывание в скобках правдивое», если результат вычислений в круглых скобках = true. В ином случае выводим: «Высказывание в скобках ложное».
Так как выражение (3 < 2) возвращает false, то и в консоли видим: «Высказывание в скобках ложное».
Вложенные конструкции
Допустим, мы хотим проверить некое условие, и если оно не выполнилось — проверить другое условие и так далее. Сделать это можно двумя способами.
1. Вложенный if
Синтаксис тут такой:
if (условие1) {
//действия, если условие1 выполнено;
} else {
if (условие2) {
//действия, если условие2 выполнено;
}
<…>
else {
//действия, если все предыдущие условия не выполнились;
}
Пример:
2. Конструкция else if
Каждое логическое условие записывают через комбинацию else if, после которых в круглых скобках идёт альтернативное условие. Последний вариант (если ни одно из условий не сработало) записывается через else без условия.
Синтаксически это выглядит так:
if (условие1) {
//действия, если условие1 выполнено;
}
else if (условие2) {
//действия, если условие2 выполнено;
}
else if (условие3) {
//действия, если условие3 выполнено;
}
<…>
else {
//действия, если условие последнего if тоже не выполнилось;
}
Пример:
Каждое следующее условие проверяется только в том случае, если предыдущее не выполнилось. Как только найдётся одно правдивое условие (или мы достигнем последнего else), выполнится код в фигурных скобках после этого условия, а оставшаяся цепочка условий будет пропущена.
Иногда условий else if нужно довольно много:
Такой код сложно воспринимать: увеличение глубины вложенности быстро сделало его запутанным. Для таких случаев придуман оператор switch.
Оператор множественного выбора (switch)
Он применяется, когда нужно выполнить один из нескольких блоков кода в зависимости от значения аргумента.
Выгода от switch тем очевиднее, чем больше проверок и вариантов действий нам нужно.
Например:
В круглых скобках указывается аргумент для switch, а в каждом блоке case — чему этот аргумент должен равняться, чтобы выполнился код после двоеточия.
В нашем случае выполнится case 5, так как переменная dayOfWeekNum (порядок дня в неделе) равна 5.
В конце каждого блока case мы ставим break. Если этого не сделать, то выполнится также код из следующего блока case и так далее.
Например:
Если для нескольких значений аргумента нужно выполнять один и тот же код, то блоки case можно объединить.
Например, для будних дней (dayOfWeekNum от 1 до 5) будем выводить, какой это по счёту рабочий день, а для уикенда — первый или второй это выходной:
Теперь при значении переменной dayOfWeekNum от 1 до 5 выполнится один и тот же код, и для значений 6 и 7 — тоже одинаковый.
Также можно задать действие, если ни одно из условий не сработало. Делается это с помощью ключевого слова default:
Примечание. Слово break означает выход из switch…case. Поэтому если ваш блок default стоит не последним, то тоже завершайте его словом break, иначе выполнится код из следующего case.
Ограничения для оператора switch
Есть ряд условий, которые следует выполнять:
- Тип значений в case должен соответствовать типу значения в switch.
- Не поддерживаются типы boolean, long, с плавающей запятой (double, float).
- В case должны быть указаны либо константы, либо выражения, значения которых компилятор сможет вычислить.
Например, компилятор сможет вычислить выражение (1 + 2 + 3) * 4 до запуска кода и подставит вместо него итоговое значение 24. А значение переменной или результат метода компилятор до запуска программы предсказать не может, поэтому ни переменную, ни метод подставлять в case нельзя. - Значения в case не могут повторяться, а default у каждого switch может быть только один.
Обновлённый оператор switch в Java 14
С версии 14 Java поддерживает новый синтаксис switch:
Теперь нам не нужно писать break, а двоеточие заменено на стрелочку и фигурные скобки. Блок default по-прежнему не обязателен.
Если код блока case состоит всего из одной строки, то фигурные скобки можно не использовать:
В операторе switch прошлой версии мы задавали одно действие для нескольких значений case, располагая пустые case над case c кодом:
В новой версии для этого хватает одного case, а связанные с ним значения разделяются запятой. Например:
Теперь switch — уже не просто оператор ветвления, он может вернуть значение. Это делается с помощью вспомогательного оператора yield.
Пример:
В новой версии switch, когда нам нужно лишь вернуть значение из соответствующего case (он должен быть без кода), — можно обойтись и без слова yield:
Советы и упрощения
1. Фигурные скобки после if или else разрешено не ставить, если тело блока состоит всего из одной строки.
Однако всё же советую ставить скобки, так вы научитесь быть последовательными и облегчите рефакторинг кода.
2. Вот так писать не следует (внимание на условие в if):
Код будет работать, но сравнение boolean с boolean в условии — это лишняя операция.
Поскольку метод isMoreFive сам возвращает булево значение — напишите вот так:
Здесь снова ненужное сравнение:
Чтобы не было лишней операции — пишите вот так:
Условие по-прежнему выполняется, когда isMoreFive возвращает false, однако от бессмысленного сравнения мы избавились.
Тернарный оператор
Тернарный оператор — это лаконичная замена if-else. Он возвращает вместо себя одно из выражений в зависимости от истинности условия (логического высказывания).
Синтаксис тернарного оператора:
условие ? выражение1 : выражение2
Если условие выполняется, то оператор возвращает выражение1, иначе — выражение2. Значения возвращаемых выражений могут быть любого типа.
Примеры:
Как записать то же самое с if:
Как видно, вариант с тернарным оператором намного короче.
Тернарные операторы допустимо вкладывать друг в друга:
И то же самое с помощью if:
Конечно, так длиннее — но и читабельнее.
Оператор instanceof
Есть ещё один оператор, который возвращает булево значение, — это instanceof.
Он проверяет принадлежность переменной к какому-то классу.
Когда используют instanceof?
Если классы объектов нужно узнать во время выполнения программы.
Допустим, есть два потока исполнения. В первом создаются объекты разных классов, а в другом они используются. С instanceof легко выяснять класс каждого объекта, который получает второй поток.
Класс объекта важно знать и для приведения типов. Хотя большинство подобных проблем выявляет компилятор, но приведение типов при иерархии классов чревато ошибками, которые всплывают только во время работы.
Вообще, instanceof используется редко, потому что обычно типы объектов известны сразу. Применять этот оператор считается дурным тоном, это признак плохой программной архитектуры. Но его используют в обобщённых процедурах, которые оперируют объектами из сложной иерархии классов.
Как работать с instanceof
Рассмотрим на примере:
Объект c принадлежит только к классу C. Нам пришлось привести его к классу Object, чтобы можно было проверить на соответствие классу A.
Иначе компилятор сразу бы увидел, что объект класса C не принадлежит к классу A, — и не дал бы запустить программу с ошибкой несовместимости типов:
Упрощённый оператор instanceof в Java 15
Раньше был допустим только такой синтаксис:
То есть мы сначала проверяем, что object может быть приведён к какому-то типу Type, — это и делает оператор instanceof, а внутри условия приводим объект к этому типу и записываем результат в новую переменную.
В Java 15 появилась конструкция упрощённого приведения:
Мы проверили, что object можно привести к Type, и сразу в условии привели его к этому типу, а результат записали в переменную t. Эту переменную можно использовать внутри блока if.
Что дальше?
Сперва подытожим:
- мы познакомились с типом Boolean;
- рассмотрели операторы сравнения <, >, <=, >=, ==, !=, а также instanceof;
- изучили операторы ветвления if, switch и тернарный оператор.
Пора рассмотреть условные выражения, включающие не только операторы сравнения, но и логические операторы.