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

switch со стрелкой

В классическом switch комнаты за дверями соединены проходами, и без break выполнение идёт дальше. С Java 14 у switch есть вторая форма — со стрелкой ->. В ней у каждой двери своя отдельная комната, без проходов в соседние: вошли, выполнили ветку, вышли.

JAVA
public class Main {
    public static void main(String[] args) {
        int day = 7;
        switch (day) {
            case 6, 7 -> System.out.println("weekend"); // weekend
            default -> System.out.println("workday");
        }
    }
}

Давайте пройдём по программе:

  1. switch (day) вычисляет day и получает 7.
  2. case 6, 7 -> — семёрка есть в списке, и ветка печатает weekend.
  3. После ветки switch заканчивается: break не нужен, и до default дело не доходит.

Ветки со стрелкой

Вместо двоеточия после значений стоит стрелка ->, а за ней код ветки. Разберём, как такую ветку записывают.

Одна инструкция

После стрелки пишут одну инструкцию, как в примере. Ветка выполняет её и выходит из switch. Проваливания нет, поэтому break не пишут.

Блок в фигурных скобках

Если инструкций несколько, их берут в фигурные скобки: case 6, 7 -> { … }. После закрывающей скобки ветка тоже заканчивается, и выполнение покидает switch.

Несколько значений

Значения одной ветки перечисляют через запятую: case 6, 7 ->. Это замена меткам, которые в классическом switch ставят подряд.

Стрелки и двоеточия в одном switch смешивать нельзя: компилятор ответит different case kinds used in the switch.

switch-выражение

Чаще всего switch нужен, чтобы выбрать значение: название дня, цену, текст сообщения. switch умеет и сам давать значение, как оператор ?:. Такой switch называют switch-выражением, и обычно его пишут со стрелками:

JAVA
int day = 7;
String kind = switch (day) {
    case 6, 7 -> "weekend";
    default -> "workday";
};
System.out.println(kind); // weekend

Разберём по шагам:

  1. switch (day) выбирает ветку case 6, 7.
  2. Значение после стрелки, "weekend", становится значением всего switch.
  3. Это значение попадает в переменную kind.
  4. Точка с запятой после закрывающей скобки обязательна: вся запись — одно объявление String kind = …;.

На собеседовании часто спрашивают, чем switch-выражение отличается от классического switch. Ждут трёх пунктов:

  • оно даёт значение;
  • его ветки со стрелкой не проваливаются;
  • оно обязано покрыть все возможные значения.

yield

Иногда ветке нужно сделать несколько действий, прежде чем отдать значение. Тогда её берут в фигурные скобки, а значение отдают словом yield:

JAVA
int day = 3;
String kind = switch (day) {
    case 6, 7 -> "weekend";
    default -> {
        System.out.println("day " + day); // day 3
        yield "workday";
    }
};
System.out.println(kind); // workday

Ветка default сначала печатает day 3. Затем yield "workday" отдаёт значение всему switch и завершает ветку. В ветке из одного значения yield не нужен: стрелка сама отдаёт то, что стоит после неё.

Ответ на любой случай

switch-выражение обязано дать значение при любом значении переменной, иначе в kind нечего было бы положить. Компилятор проверяет это заранее, ещё до запуска.

Здесь картинка с дверями хромает. В коридоре все двери можно пересчитать, а у типа int больше четырёх миллиардов значений. Поэтому вместо перечисления нужна ветка default — общая комната для всех дверей, которых нет в списке.

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

Перечислили все месяцы, но забыли default:

JAVA
int month = 12;
String season = switch (month) { // ✗
    case 12, 1, 2 -> "winter";
    case 3, 4, 5 -> "spring";
    case 6, 7, 8 -> "summer";
    case 9, 10, 11 -> "autumn";
};
TEXT
error: the switch expression does not cover all possible input values

Все двенадцать месяцев на месте, но компилятор не знает, что в month бывают только числа от 1 до 12. Для него month — любой int, например 13 или -5, а для таких чисел ветки нет. Добавьте ветку default -> "unknown";, и программа скомпилируется.

Главное

  • В ветке со стрелкой нет проваливания, и break не нужен.
  • Несколько значений одной ветки перечисляют через запятую: case 6, 7 ->.
  • switch-выражение даёт значение; из ветки в фигурных скобках его отдают через yield.
  • switch-выражение обязано покрыть все значения, поэтому для int нужна ветка default.