switch
Когда одну переменную сравнивают с длинным списком значений, цепочка if ... else if становится громоздкой. switch записывает такой выбор короче: значение проверяется по меткам case, и выполняется подходящая ветка.
Стрелочная форма
После switch в скобках пишут проверяемое значение, а в блоке — метки case со стрелкой ->. Выполняется только ветка совпавшей метки; default срабатывает, если не подошла ни одна:
void main() {
int day = 3;
switch (day) {
case 1 -> IO.println("Понедельник");
case 2 -> IO.println("Вторник");
case 3 -> IO.println("Среда");
default -> IO.println("Другой день");
}
}Результат:
Средаswitch работает с целыми числами, символами, строками и перечислениями (о них — в главе об ООП). Метки проверяются на точное равенство, поэтому для диапазонов вроде «от 1 до 5» удобнее if.
Несколько значений
Одна ветка может отвечать сразу за несколько значений — их перечисляют через запятую:
void main() {
String day = "сб";
switch (day) {
case "пн", "вт", "ср", "чт", "пт" -> IO.println("Рабочий день");
case "сб", "вс" -> IO.println("Выходной");
default -> IO.println("Неизвестный день");
}
}Результат:
Выходнойswitch-выражение
switch может не только выполнять действия, но и возвращать значение. Тогда его называют выражением и результат записывают в переменную. В конце ставят точку с запятой:
void main() {
int month = 7;
String season = switch (month) {
case 12, 1, 2 -> "Зима";
case 3, 4, 5 -> "Весна";
case 6, 7, 8 -> "Лето";
default -> "Осень";
};
IO.println(season);
}Результат:
ЛетоВыражение должно вернуть значение при любом входе, поэтому default здесь обязателен.
yield
Если ветке нужно несколько действий, её код берут в фигурные скобки, а значение возвращают словом yield:
void main() {
int items = 5;
double discount = switch (items) {
case 1, 2 -> 0;
default -> {
IO.println("Скидка за количество");
yield 0.1;
}
};
IO.println(discount);
}Результат:
Скидка за количество
0.1Классическая форма
В старом коде встречается switch с двоеточиями. В нём после совпавшей метки выполняется весь код до слова break — даже код следующих меток:
void main() {
int level = 2;
switch (level) {
case 1:
IO.println("Новичок");
break;
case 2:
IO.println("Опытный");
break;
default:
IO.println("Эксперт");
}
}Результат:
ОпытныйВ новом коде используйте стрелки: они короче и не требуют break.
Частая ошибка
В классической форме легко забыть break. Тогда выполнение «проваливается» в следующие ветки:
void main() {
int level = 1;
switch (level) {
case 1:
IO.println("Новичок");
case 2:
IO.println("Опытный");
break;
default:
IO.println("Эксперт");
}
}Результат:
Новичок
ОпытныйКомпилятор не предупреждает о пропущенном break. Стрелочная форма решает проблему: в ней проваливания не бывает.