Сравнения и логика
Чему вы научитесь:
- сравнивать значения и соединять условия через
&&,||и!; - выбирать, какой код выполнить, с помощью
if,elseи оператора?:; - писать классический
switchи объяснять, зачем в нёмbreak; - получать значение из
switchсо стрелкой.
Представьте развилку с указателем: «Налево — если вам меньше 18 лет, направо — всем остальным». Чтобы выбрать дорогу, вы отвечаете на вопрос указателя. Ответов всего два: да или нет.
Программа тоже постоянно выбирает: пустить пользователя или нет, напечатать одно сообщение или другое. Для этого ей нужны вопросы с ответом «да» или «нет». В Java такой ответ — значение типа boolean: true или false. Вы уже встречали этот тип среди восьми примитивных. Вопрос программе задают сравнением:
public class Main {
public static void main(String[] args) {
int age = 17;
boolean adult = age >= 18;
System.out.println(adult); // false
System.out.println(age == 17); // true
System.out.println(age != 17); // false
}
}Давайте разберём программу по строкам:
int age = 17;заводит переменную с возрастом.age >= 18спрашивает: «ageбольше 18 или равен 18?». Ответfalseпопадает в переменнуюadultтипаboolean.System.out.println(adult)печатаетfalse.age == 17спрашивает, равен лиageчислу 17, и даётtrue.age != 17спрашивает обратное и даётfalse.
Операторы сравнения
Операторы сравнения сравнивают два значения и дают boolean. В Java их шесть:
| Оператор | Что спрашивает | Пример |
|---|---|---|
== | равны ли значения | 5 == 5 даёт true |
!= | различаются ли значения | 5 != 5 даёт false |
< | меньше ли левое | 3 < 5 даёт true |
<= | меньше или равно | 5 <= 5 даёт true |
> | больше ли левое | 3 > 5 даёт false |
>= | больше или равно | 3 >= 5 даёт false |
Сравнение на равенство пишут двумя знаками: ==. Один знак = — это присваивание: он кладёт значение в переменную, а не задаёт вопрос.
Логические операторы
Указатель может задать и сложный вопрос: «Налево — если идёт дождь и у вас нет зонта». Такой вопрос собран из двух простых. Логические операторы соединяют несколько ответов boolean в один:
int age = 25;
boolean hasTicket = false;
System.out.println(age >= 18 && hasTicket); // false
System.out.println(age >= 18 || hasTicket); // true
System.out.println(!hasTicket); // trueИ: &&
Запись a && b даёт true, только когда истинны обе части. В примере возраст подходит, а билета нет, поэтому результат — false.
ИЛИ: ||
Запись a || b даёт true, когда истинна хотя бы одна часть. Возраст подходит, и этого хватает для true. Результат false получится, только если ложны обе части.
НЕ: !
Оператор ! ставят перед одним значением, и он меняет ответ на противоположный: !false — это true. Читается он как «не»: !hasTicket значит «билета нет».
Оператор && связывает сильнее, чем ||, — как умножение сильнее сложения. Если в условии есть оба, ставьте скобки: запись (a || b) && c читается без догадок.
Сокращённое вычисление
Java вычисляет && и || слева направо и останавливается, как только ответ известен. Если левая часть && ложна, весь ответ уже false, и правую часть Java не вычисляет. У || то же самое с истинной левой частью: ответ уже true. Такое поведение называют сокращённым вычислением.
На развилке так же. Если на вопрос «Идёт дождь?» ответ «нет», спрашивать про зонт уже незачем:
int x = 0;
System.out.println(x != 0 && 10 / x > 1); // falseРазберём, что здесь происходит:
x != 0даётfalse.- Левая часть
&&ложна, поэтому Java не вычисляет10 / x > 1. - Деления на ноль не происходит, и программа печатает
false.
Деление целого числа на ноль бросает исключение ArithmeticException и останавливает программу. Здесь до деления дело не доходит. Левая часть работает как сторож: она пропускает к делению только x, не равный нулю.
На собеседовании часто спрашивают, что такое сокращённое вычисление и почему проверку на ноль пишут слева.
Только boolean
Здесь указатель на развилке и Java расходятся. Человек может ответить «не знаю» или «скорее да». У Java третьего ответа нет: где нужен ответ, подходит только boolean. Число ответом не считается, хотя в некоторых языках ноль означает «нет».
Поэтому компилятор не пропустит такие записи, если x имеет тип int:
boolean ok = x;— ошибкаincompatible types: int cannot be converted to boolean;!x— ошибкаbad operand type int for unary operator '!';0 < x < 10— ошибкаbad operand types for binary operator '<'.
Третья запись привычна по математике, но в Java 0 < x сначала даёт boolean, а сравнивать true с числом 10 нельзя. Двойное сравнение пишут через &&: 0 < x && x < 10.
Частая ошибка
Проверку на ноль поставили справа:
int x = 0;
System.out.println(10 / x > 1 && x != 0); // ✗Exception in thread "main" java.lang.ArithmeticException: / by zeroJava вычисляет && слева направо, поэтому первым выполняется деление 10 / x. До проверки x != 0 дело не доходит: программа останавливается с исключением. Сторож должен стоять слева: x != 0 && 10 / x > 1.
Главное
- Операторы
==,!=,<,<=,>,>=даютboolean;==сравнивает, а=присваивает. &&истинно, когда истинны обе части,||— когда хотя бы одна, а!меняет ответ на обратный.&&и||вычисляются слева направо и пропускают правую часть, когда ответ уже известен.- Там, где нужен ответ «да» или «нет», Java принимает только
boolean, а не число.