Перейти к содержимому
Теория · Условия · урок 1 из 8

Сравнения и логика

Чему вы научитесь

Чему вы научитесь:

  • сравнивать значения и соединять условия через &&, || и !;
  • выбирать, какой код выполнить, с помощью if, else и оператора ?:;
  • писать классический switch и объяснять, зачем в нём break;
  • получать значение из switch со стрелкой.

Представьте развилку с указателем: «Налево — если вам меньше 18 лет, направо — всем остальным». Чтобы выбрать дорогу, вы отвечаете на вопрос указателя. Ответов всего два: да или нет.

Программа тоже постоянно выбирает: пустить пользователя или нет, напечатать одно сообщение или другое. Для этого ей нужны вопросы с ответом «да» или «нет». В Java такой ответ — значение типа boolean: true или false. Вы уже встречали этот тип среди восьми примитивных. Вопрос программе задают сравнением:

JAVA
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
    }
}

Давайте разберём программу по строкам:

  1. int age = 17; заводит переменную с возрастом.
  2. age >= 18 спрашивает: «age больше 18 или равен 18?». Ответ false попадает в переменную adult типа boolean.
  3. System.out.println(adult) печатает false.
  4. age == 17 спрашивает, равен ли age числу 17, и даёт true.
  5. age != 17 спрашивает обратное и даёт false.

Операторы сравнения

Операторы сравнения сравнивают два значения и дают boolean. В Java их шесть:

ОператорЧто спрашиваетПример
==равны ли значения5 == 5 даёт true
!=различаются ли значения5 != 5 даёт false
<меньше ли левое3 < 5 даёт true
<=меньше или равно5 <= 5 даёт true
>больше ли левое3 > 5 даёт false
>=больше или равно3 >= 5 даёт false

Сравнение на равенство пишут двумя знаками: ==. Один знак = — это присваивание: он кладёт значение в переменную, а не задаёт вопрос.

Логические операторы

Указатель может задать и сложный вопрос: «Налево — если идёт дождь и у вас нет зонта». Такой вопрос собран из двух простых. Логические операторы соединяют несколько ответов boolean в один:

JAVA
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. Такое поведение называют сокращённым вычислением.

На развилке так же. Если на вопрос «Идёт дождь?» ответ «нет», спрашивать про зонт уже незачем:

JAVA
int x = 0;
System.out.println(x != 0 && 10 / x > 1); // false

Разберём, что здесь происходит:

  1. x != 0 даёт false.
  2. Левая часть && ложна, поэтому Java не вычисляет 10 / x > 1.
  3. Деления на ноль не происходит, и программа печатает 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.

Частая ошибка

Проверку на ноль поставили справа:

JAVA
int x = 0;
System.out.println(10 / x > 1 && x != 0); // ✗
TEXT
Exception in thread "main" java.lang.ArithmeticException: / by zero

Java вычисляет && слева направо, поэтому первым выполняется деление 10 / x. До проверки x != 0 дело не доходит: программа останавливается с исключением. Сторож должен стоять слева: x != 0 && 10 / x > 1.

Главное

  • Операторы ==, !=, <, <=, >, >= дают boolean; == сравнивает, а = присваивает.
  • && истинно, когда истинны обе части, || — когда хотя бы одна, а ! меняет ответ на обратный.
  • && и || вычисляются слева направо и пропускают правую часть, когда ответ уже известен.
  • Там, где нужен ответ «да» или «нет», Java принимает только boolean, а не число.