1. Выражения vs Команды
Все команды в Java делятся на две категории: команды (Statement) и выражения (Expression). Про команду обычно говорят, что она выполняется, а про выражение — что оно вычисляется. Но это не главное.
Основное отличие между командой и выражением в том, что у выражения есть результат вычисления. У этого результата, во‑первых, есть тип, а во‑вторых, этот результат можно куда-то присвоить, ну или использовать в каком-то другом выражении.
Примеры:
| Код | Примечания |
|---|---|
|
Команда |
|
Выражение, тип boolean |
|
Выражение, тип совпадает с типом переменной i |
|
Выражение, тип совпадает с типом переменной x |
И что это нам дает?
Во-первых, мы можем использовать тот факт, что очень много команд на самом деле являются выражением (имеют результат вычисления). Например, такой код будет работать:
int x, y, z;
x = y = z = 1; // x = (y = (z = 1));
Во-вторых, мы можем игнорировать результат вычисления выражения, если хотим.
console.nextLine(); //игнорируем результат ввода
Игнорировать результат вычисления выражения нужно, например, если выражение кроме результата делает еще что-то полезное, и нам это действие важно, а сам результат — нет.
2. Тернарный оператор
Этот лайфхак уже поинтереснее предыдущего. В Java есть специальный тернарный (тройной) оператор. Чем-то он похож на сокращенную запись оператора if–else:
Условие ? Выражение1 : Выражение2;
Если условие истинно, то выполняется выражение1 иначе выполняется выражение2. После условия следует знак вопроса, а два выражения разделены двоеточием.
Основное отличие тернарного оператора от оператора if-else в том, что тернарный оператор является выражением, а значит его результат можно чему-нибудь присвоить.
Например, мы хотим вычислить минимум двух чисел. С использованием тернарного оператора этот код будет выглядеть так:
int a = 2;
int b = 3;
int min = a < b ? a : b;
Или, допустим, вам нужно присвоить переменной разные значения в зависимости от какого-то условия. Как это сделать?
Вариант первый — воспользоваться оператором if-else:
int age = 25;
int money;
if (age > 30)
money = 100;
else
money = 50;
Второй вариант — использовать тернарный оператор, то есть сокращенную запись оператора if-else:
int age = 25;
int money = age > 30 ? 100 : 50;
Так что же лучше использовать: оператор if-else или тернарный оператор? С точки зрения скорости выполнения, особой разницы нет. Здесь скорее вопрос читаемости кода. И это очень важный момент: код должен не только правильно работать, но и легко читаться другими программистами.
Самый простой критерий может быть таким: если код помещается в одну строку — используйте тернарный оператор, если в одну строку он уже не помещается — лучше использовать if-else.
3. Нюансы работы
Типы значений
Важно помнить: обе ветки тернарного оператора (<значение_если_истина> и <значение_если_ложь>) должны быть одного типа, либо совместимы (например, оба String, либо оба int).
Работает:
int a = 10, b = 20;
int max = (a > b) ? a : b; // обе ветки — int
Ошибка компиляции:
int a = 10, b = 20;
// String и int несовместимы
String result = (a > b) ? "больше" : 0; // Ошибка компиляции: нельзя присвоить int в переменную типа String
Правильный вариант:
int a = 10, b = 20;
String result = (a > b) ? "больше" : "меньше или равно";
Пример: работа с числами
Посчитаем абсолютное значение с помощью тернарного оператора:
int number = -5;
int abs = (number >= 0) ? number : -number;
System.out.println(abs); // 5
4. Встраивание тернарного оператора в приложение
Давайте напишем некое диалоговое приложение: кроме приветствия, программа будет говорить пользователю, сколько лет ему будет через год, и указывать, будет ли он совершеннолетним.
System.out.print("Введите ваше имя: ");
String name = console.nextLine();
System.out.print("Введите ваш возраст: ");
int age = console.nextInt();
int nextYear = age + 1;
String status = (nextYear >= 18) ? "совершеннолетний" : "несовершеннолетний";
System.out.println("Привет, " + name + "! В следующем году вам будет " + nextYear + ". Вы будете " + status + ".");
Объясним детали:
Переменная status вычисляется через тернарный оператор: если возраст через год не менее 18, значит, пользователь будет совершеннолетним (или останется таким).
5. Вложенные тернарные операторы — осторожно!
Тернарный оператор можно вкладывать друг в друга (в каждой из веток может быть ещё один тернарник). Но… от этого обычно болит голова, особенно у того, кто будет читать код после вас (даже если это вы через 2 дня).
Пример: определение категории по возрасту
String category = (age < 7) ? "дошкольник" :
(age < 18) ? "школьник" :
(age < 65) ? "взрослый" : "пенсионер";
Таблица принятия решения:
| Возраст | Условие | Результат |
|---|---|---|
| < 7 | |
дошкольник |
| 7–17 | |
школьник |
| 18–64 | |
взрослый |
| 65 и больше | иначе | пенсионер |
Такой код ещё можно читать, но если логика сложнее — лучше использовать if-else if-else.
6. Лайфхак: тернарный оператор и тип boolean
Иногда нужно написать выражение типа:
boolean adult = (age >= 18) ? true : false;
Но это избыточно. Само выражение (age >= 18) уже возвращает boolean. Поэтому его можно сократить до:
boolean adult = (age >= 18);
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ