1. Что нового в switch
Если вдруг вы писали на Java до 14-й версии, то switch выглядел примерно так:
switch (day)
{
case MONDAY:
System.out.println("Начало недели!");
break;
case FRIDAY:
System.out.println("Пятница, ура!");
break;
default:
System.out.println("Обычный день.");
break;
}
Вроде бы ничего страшного, но:
- Нужно не забыть break (иначе «провалимся» в следующий case).
- Много повторяющегося кода.
- Если хочется вернуть значение, приходится объявлять переменную заранее и присваивать ей значение внутри каждого case.
Java 14+ решила: хватит этого! Пора сделать switch более удобным и современным.
Основные нововведения:
- Switch стал выражением, а не только оператором — теперь он может возвращать значение.
- Новый синтаксис со стрелкой -> вместо двоеточий и break.
- Несколько case через запятую — для одинаковой логики.
- Компилятор проверяет, что все варианты обработаны (особенно с enum).
- Нет риска «проваливания» (fall-through) — теперь это возможно только явно.
2. Синтаксис switch-выражения
switch (значение)
{
case A, B -> результат1;
case C -> {
// несколько действий
yield результат2;
}
default -> результатПоУмолчанию;
}
-> и
yield
Базовый пример
Давайте сразу к делу. Вот как теперь можно возвращать значение из switch:
DayOfWeek day = DayOfWeek.MONDAY;
String message = switch (day)
{
case MONDAY, FRIDAY, SUNDAY -> "Короткая неделя или выходной!";
case TUESDAY -> "Вторник — день тяжёлый.";
case WEDNESDAY, THURSDAY -> "Середина недели!";
case SATURDAY -> "Ура, суббота!";
// Обязательно должен быть default, если не все варианты обработаны
default -> "Какой-то странный день...";
};
System.out.println(message);
Что здесь происходит:
- switch (day) — выражение, возвращающее значение.
- После стрелки -> указывается результат для этого case.
- Несколько case можно объединить через запятую.
- Нет ни одного break — Java сама знает, где заканчивается ветка.
- Можно сразу присваивать результат переменной message.
Пример с числами
int code = 404;
String result = switch (code)
{
case 200 -> "OK";
case 400, 404 -> "Ошибка клиента";
case 500 -> "Ошибка сервера";
default -> "Неизвестный код";
};
System.out.println(result);
Пример со строками
String command = "start";
String status = switch (command)
{
case "start" -> "Запуск!";
case "stop" -> "Остановка!";
case "pause" -> "Пауза...";
default -> "Неизвестная команда";
};
System.out.println(status);
Использование блока с yield
Иногда хочется выполнить несколько действий для одного case (например, вычислить что-то сложное или сделать логирование). Для этого можно использовать блок { ... } и ключевое слово yield:
int n = 7;
String parity = switch (n % 2)
{
case 0 -> "Чётное";
case 1 ->
{
System.out.println("Обнаружено нечётное число: " + n);
yield "Нечётное";
}
default -> "Что-то странное";
};
System.out.println(parity);
Важно: в блоке обязательно должен быть yield, который возвращает значение для этого case.
3. Преимущества нового синтаксиса
Нет необходимости в break
В классическом switch забытый break — источник боли и загадочных багов. В новом синтаксисе break не нужен вообще: каждая ветка завершается автоматически.
Компилятор проверяет обработку всех вариантов
Если вы используете enum и не обработали все значения — компилятор не даст собрать проект без default. Это делает код надёжнее.
Нет "проваливания" (fall-through)
В классическом switch, если забыть break, выполнение «провалится» в следующий case. В новом синтаксисе это невозможно (разве что вы используете блок с инструкциями и явно пишете break — но здесь он не нужен).
Код компактнее и читаемее
Сравните сами:
До:
String result;
switch (status) {
case "OK":
result = "Всё хорошо";
break;
case "ERROR":
result = "Ошибка";
break;
default:
result = "Неизвестно";
break;
}
После:
String result = switch (status) {
case "OK" -> "Всё хорошо";
case "ERROR" -> "Ошибка";
default -> "Неизвестно";
};
Несколько case — одна логика
case MONDAY, FRIDAY, SUNDAY -> "Выходной или короткий день!";
4. Сравнение с классическим switch
| Особенность | Классический switch | Новый switch |
|---|---|---|
| break обязателен | Да | Нет |
| Проваливание (fall-through) | Да | Нет |
| Может возвращать значение | Нет (только через переменную) | Да (выражение) |
| Несколько case через запятую | Нет | Да |
| Проверка всех вариантов | Нет | Да (особенно с enum) |
| Компактность | Много кода | Коротко и ясно |
| Использование с enum и строками | Да | Да |
5. Совместимость с enum и строками
Пример с enum
Допустим, у нас есть перечисление:
enum DayOfWeek
{
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Используем его в новом switch:
DayOfWeek today = DayOfWeek.WEDNESDAY;
String mood = switch (today)
{
case MONDAY -> "Тяжело вставать...";
case FRIDAY -> "Скоро выходные!";
case SATURDAY, SUNDAY -> "Ура, отдых!";
default -> "Рабочий день.";
};
System.out.println(mood);
Пример со String
String season = "summer";
String activity = switch (season)
{
case "winter" -> "Кататься на коньках";
case "summer" -> "Плавать в озере";
case "autumn" -> "Собирать грибы";
case "spring" -> "Слушать пение птиц";
default -> "Неизвестное время года";
};
System.out.println(activity);
6. Переписываем старый switch на новый стиль
Было:
int day = 3;
String dayName;
switch (day)
{
case 1:
dayName = "Понедельник";
break;
case 2:
dayName = "Вторник";
break;
case 3:
dayName = "Среда";
break;
default:
dayName = "Неизвестный день";
break;
}
System.out.println(dayName);
Стало:
int day = 3;
String dayName = switch (day)
{
case 1 -> "Понедельник";
case 2 -> "Вторник";
case 3 -> "Среда";
default -> "Неизвестный день";
};
System.out.println(dayName);
Ещё пример: несколько case — одна логика
int score = 5;
String grade = switch (score)
{
case 5, 6, 7 -> "Хорошо";
case 8, 9, 10 -> "Отлично";
default -> "Нужно постараться";
};
System.out.println(grade);
7. Типичные ошибки и особенности
Ошибка №1: отсутствие default, если не все варианты обработаны. Если вы используете switch-выражение с типом, у которого могут быть значения вне перечисленных case (например, с int или String), компилятор потребует default. Для enum, если вы не обработали все значения, default тоже обязателен.
Ошибка №2: забыли yield в блоке. Если используете фигурные скобки для case (нужно выполнить несколько действий), не забудьте про yield — без него компилятор выдаст ошибку: "Missing yield statement".
Ошибка №3: несовпадение типов. Все ветки switch-выражения должны возвращать значения одного типа; иначе компилятор не пропустит код.
Ошибка №4: дублирование значений case. Указывать один и тот же case дважды нельзя — компилятор сразу сообщит об ошибке.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ