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

switch и break

Цепочка else if подходит для разных вопросов. Но когда одну переменную сравнивают с длинным списком значений, цепочка повторяет одно и то же: light == 'g', потом light == 'y', потом ещё раз. Для такого выбора в Java есть инструкция switch.

Представьте коридор с рядом дверей. На каждой двери написано значение: 'g', 'y'. switch один раз смотрит, что лежит в переменной, и открывает дверь с таким же значением. Но комнаты за дверями соединены проходами: из своей комнаты можно пройти в следующую, а оттуда ещё дальше. Остановит вас только выход наружу, и этот выход называется break.

Вот светофор, записанный через switch:

JAVA
public class Main {
    public static void main(String[] args) {
        char light = 'y';
        switch (light) {
            case 'g':
                System.out.println("go");
                break;
            case 'y':
                System.out.println("wait"); // wait
                break;
            default:
                System.out.println("stop");
        }
    }
}

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

  1. char light = 'y'; — горит жёлтый.
  2. switch (light) один раз берёт значение light и ищет дверь case 'y'.
  3. case 'g': не подходит, и его код программа пропускает.
  4. case 'y': подходит: программа входит сюда и печатает wait.
  5. break выводит из switch, поэтому код default не выполняется.

Части switch

Внутри фигурных скобок switch стоят части трёх видов.

case

Запись case 'y': называют меткой. Это дверь с надписью:

  • после case пишут значение и двоеточие;
  • значение — константа, подходящая по типу к переменной в скобках switch;
  • одно значение не может стоять на двух дверях: компилятор ответит duplicate case label.

Код ветки пишут после метки, обычно на следующих строках.

break

break — выход наружу. Выполнение сразу переходит к первой инструкции после закрывающей скобки switch.

default

Метка default — дверь для всех остальных значений. Её код выполняется, когда не подошёл ни один case. В примере это любой сигнал, кроме зелёного и жёлтого. Если default нет, в таком случае не выполнится ничего.

Проваливание

Что будет, если забыть break? Выполнение не остановится в конце ветки. Оно перейдёт к коду следующей метки и выполнит его, не сравнивая значение. Это называют проваливанием.

В виджете тот же светофор: горит зелёный, а break после go убран. Нажимайте «Следующий шаг» и следите, какие строки выполняются после go.

ВживуюПроваливание без breakшаг 1 из 8 · рамок: 1

Переменная light хранит символ g: горит зелёный.

Подсвечена строка, которая только что выполнилась

Проваливание продолжается до первого break или до конца switch. Метка default от него не защищает: если выполнение дошло до неё по проходу, её код тоже выполнится.

Здесь коридор неточен в одном. Человек сам решает, идти ли в соседнюю комнату. Java не решает: она идёт дальше, пока не встретит break. На собеседовании любят показать switch без break и спросить, что он выведет.

Проваливание по делу

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

JAVA
String day = "sun";
switch (day) {
    case "sat":
    case "sun":
        System.out.println("weekend"); // weekend
        break;
    default:
        System.out.println("workday");
}

day равен "sun", и выполнение входит через метку case "sun":. Если бы day был равен "sat", оно вошло бы через метку выше и провалилось к тому же коду. Те же два значения можно записать одной меткой через запятую: case "sat", "sun":.

Какие значения подходят

switch работает не с любым типом:

  • подходят целые int, short, byte и символы char;
  • подходят строки String: метка case "sun" совпадает, когда в строке написано sun;
  • не подходят long, double, float и boolean.

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

Забыли break в последней ветке перед default:

JAVA
int choice = 1;
switch (choice) {
    case 1:
        System.out.println("play"); // ✗
    default:
        System.out.println("no such item");
}

Программа печатает две строки: play и no such item. Метка case 1 совпала, break в ветке нет, и выполнение провалилось в default. Компилятор пропускает такую программу без ошибки: предупреждение possible fall-through into case javac печатает только с флагом -Xlint:all. Поставьте break после первого println, и default будет срабатывать только для неизвестного пункта меню.

Главное

  • switch один раз вычисляет значение и переходит к метке case с таким же значением.
  • break выводит из switch; без него выполнение проваливается в следующие ветки, не проверяя их метки.
  • default выполняется, когда не подошёл ни один case, или когда до него дошли проваливанием.
  • Классический switch работает с int, char и String, но не с long, double и boolean.