JavaRush/Java блог/Java Developer/Оператор switch в Java
Автор
Milan Vucic
Репетитор по программированию в Codementor.io

Оператор switch в Java

Статья из группы Java Developer
участников
Оператор switch в Java это оператор множественного выбора: он вычисляет выражение и сравнивает его по очереди с вариантами case, выполняя код совпавшего варианта. Его используют как удобную замену длинной цепочки if-else, когда веток больше двух и выбор идет по конкретному значению. Завершают ветку словом break, иначе выполнение «проваливается» в следующие case. Представьте, что вы стоите на развилке, как богатырь с известной картины. Налево пойдешь, коня потеряешь, направо пойдешь, знания обретешь. Как запрограммировать такую ситуацию? Вы уже, скорее всего, знаете, что подобный выбор мы совершаем с помощью конструкций if-then и if-then-else.

Кратко

  • switch это оператор множественного выбора: он сравнивает значение выражения с вариантами case и выполняет совпавший.
  • Удобен, когда веток больше двух, вместо длинной цепочки if-else.
  • Выражение может быть byte, short, char, int, их обертками, String (с Java 7) и Enum.
  • break завершает switch; без него выполнение «проваливается» в следующие case (fall-through).
  • Несколько case подряд позволяют выполнить один код для разных значений.
  • В новых версиях switch стал выражением: стрелочный синтаксис case X -> ... (Java 12+) и возврат значения через yield (Java 13+).
if (turn_left) {
    System.out.println(«Коня потеряешь»);
}
if (turn_right) {
    System.out.println(“Знания обретешь”);
}
else
    System.out.println(“Так и будешь стоять?”);
А что, если таких дорожек не две, а 10? Есть дорожка «совсем направо», «чуть левее», «еще чуть-чуть левее» и так далее, в количестве 10 штук? Представьте, как разрастется ваш if-then-else код в таком варианте!
if (вариант1)
{… }
else if (вариант2)
{…}
…
else if (вариантN) ….
Итак, у вас не одна развилка условий, а несколько, скажем, 10 (тут важно, что число развилок ограничено). Для таких ситуаций есть специальный оператор выбора, switch case java.

Синтаксис switch

switch (ВыражениеДляВыбора) {
           case  (Значение1):
               Код1;
               break;
           case (Значение2):
               Код2;
               break;
...
           case (ЗначениеN):
               КодN;
               break;
           default:
               КодВыбораПоУмолчанию;
               break;
       }

Порядок выполнения

Порядок выполнения в операторе следующий:
  • Вычисляется ВыражениеДляВыбора. Далее оператор switch сравнивает полученное выражение с очередным Значением (в порядке перечисления).
  • Если ВыражениеДляВыбора совпало со Значением, то выполняется код, идущий после двоеточия.
  • Если встречается конструкция break, то управление передается за пределы команды switch.
  • Если совпадений ВыражениеДляВыбора и Значений не выявлено, то управление передается КодуВыбораПоУмолчанию.

Важные моменты

  • Тип ВыражениеДляВыбора для оператора выбора switch в Java должен быть одним из следующих:

    • byte, short, char, int.
    • Их обертки Byte, Short, Character, Integer.
    • String (начиная с Java 7).
    • Перечисление (Enum).
  • блок default необязательный, тогда в случае отсутствия совпадений ВыраженияДляВыбора и Значений не будет выполнено никаких действий.
  • break не является обязательным, если его нет, код продолжит выполнение (игнорируя дальнейшие сравнения значений в блоках case) до первого встреченного break или до конца оператора switch.
  • если необходимо выполнять один и тот же код для нескольких вариантов выбора, для исключения дублирования перед ним указываем несколько соответствующих значений в подряд идущих блоках case.

Перейдем к практике использования оператора switch в Java

Не волнуйтесь, с теорией покончили, и, после дальнейших примеров станет все гораздо понятнее. Итак, приступим. Давайте рассмотрим пример из астрономии о планетах Солнечной системы. В соответствии с последними международными положениями исключим Плутон (за свойства ее орбиты). Вспомним, что планеты у нас расположены от Солнца в следующей последовательности: Меркурий, Венера, Земля, Марс, Юпитер, Сатурн, Уран и Нептун. Создадим Java метод, который получает на вход порядковый номер планеты (относительно удаленности от Солнца), а на выходе выдает основной состав атмосферы этой планеты в виде списка List<String>. Напомню, у некоторых планет схожий состав атмосферы. Так, Венера и Марс содержат в основном углекислый газ, у Юпитера и Сатурна она состоят из водорода и гелия, а Уран и Нептун вдобавок к последней паре газов также имеет метан. Наша функция:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("Нет атмосферы");
            break;
        case 2:
        case 4: result.add("Углекислый газ");
            break;
        case 3: result.add("Углекислый газ");
            result.add("Азот");
            result.add("Кислород");
            break;
        case 5:
        case 6: result.add("Водород");
            result.add("Гелий");
            break;
        case 7:
        case 8: result.add("Метан");
            result.add("Водород");
            result.add("Гелий");
            break;
        default:
            break;
    }
    return result;
}
Обратите внимание: идентичным по составу атмосфер планетам мы сопоставили один и тот же код. А сделали мы это за счет подряд идущих конструкций case. Итого, если мы хотим получить состав атмосферы нашей с вами родной планеты, вызываем наш метод с параметром 3:
getPlanetAtmosphere(3).
System.out.println(getPlanetAtmosphere(3)) вернет нам [Углекислый газ, Азот, Кислород].
Эксперимент с break Что получится, если мы уберем все операторы break? Попробуем на практике:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("Нет атмосферы");
        case 2:
        case 4: result.add("Углекислый газ");
        case 3: result.add("Углекислый газ");
            result.add("Азот");
            result.add("Кислород");
        case 5:
        case 6: result.add("Водород");
            result.add("Гелий");
        case 7:
        case 8: result.add("Метан");
            result.add("Водород");
            result.add("Гелий");
        default:
    }
    return result;
}
Если мы распечатаем результат работы метода System.out.println(getPlanetAtmosphere(3)), то наша родная планета окажется не такой уж пригодной для жизни. Или пригодной? Судите сами: [Углекислый газ, Азот, Кислород, Водород, Гелий, Метан, Водород, Гелий], Почему так получилось? Программа выполнила все case после первого совпадения и до конца блока switch.

Излишняя оптимизация break

Заметим, что мы можем усовершенствовать метод иным расположением директив break и вариантов выбора
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("Нет атмосферы");
                break;
        case 3: result.add("Азот");
                result.add("Кислород");
        case 2:
        case 4: result.add("Углекислый газ");
                break;
        case 7:
        case 8: result.add("Метан");
        case 5:
        case 6: result.add("Водород");
                result.add("Гелий");
    }
     return result;
}
Выглядит короче, не так ли? Мы сократили общее число операторов, поигравшись с порядком следования case и перегруппировкой. Теперь каждый вид газа добавляется в список только в одной строчке кода. Листинг последнего примера метода показан только для демонстрации работы, крайне не рекомендуется писать в подобном стиле. Если автору (а тем более сторонним программистам) схожего кода предстоит его сопровождать, то будет весьма тяжело восстановить логику формирования блоков выбора и выполняемого кода для оператора switch java.

Отличия от if

При внешней схожести операторов if и switch не забывайте, что выбор вариантов выполнения оператор множественного выбора switch основывает на КОНКРЕТНОМ ЗНАЧЕНИИ, тогда как в if может быть любое логическое выражение. Учитывайте данный факт, проектируя ваш код. Коротко разницу можно свести в таблицу:
Критерийifswitch
Условиелюбое логическое выражениесравнение с конкретным значением
Число ветоклюбоеограниченное, по значениям
Типылюбые условияbyte/short/char/int, обертки, String, Enum
Когда удобнеесложные условия, диапазонымного равнозначных вариантов по значению
Давайте немного подробнее рассмотрим нововведения для switch в разных версиях Java. Коротко их можно свести в таблицу:
Версия JavaЧто появилось в switch
Java 7поддержка String в качестве выражения
Java 12стрелочный синтаксис case X ->, несколько значений через запятую, switch как выражение
Java 13возврат значения из switch через yield

Switch в Java 7

До Java 7 в качестве значения для переключателя можно было использовать byte, short, char и int примитивы. Также была поддержка enum и оберток перечисленных выше примитивных типов: Character, Byte, Short, и Integer. Но ведь часто нам нужно найти значение java switch string! Как бы это выглядело в Java 6:
DayOfWeek day = DayOfWeek.fromValue("Thursday");

switch (day) {
  case MONDAY:
     System.out.println("Today is windy !");
     break;
  case THURSDAY:
     System.out.println("Today is sunny !");
     break;
  case WEDNESDAY:
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
И enum:
public enum DayOfWeek {
  MONDAY("Monday"),
  THURSDAY("Thursday"),
  WEDNESDAY("Wednesday"),
  NOT_FOUND("Not found");

  private final String value;

  DayOfWeek(final String value) {
     this.value = value;
  }

  public static DayOfWeek fromValue(String value) {
     for (final DayOfWeek dayOfWeek : values()) {
        if (dayOfWeek.value.equalsIgnoreCase(value)) {
           return dayOfWeek;
        }
     }
     return NOT_FOUND;
  }
}
Но начиная с Java 7 добавилась возможно использовать тип String как значение для переключателя switch:
String day = "Thursday";

switch (day) {
  case "Monday":
     System.out.println("Today is windy !");
     break;
  case "Thursday":
     System.out.println("Today is sunny !");
     break;
  case "Wednesday":
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
}
Несмотря на новые возможности, подход с использованием enum более гибок и рекомендуем к использованию: этот enum мы можем переиспользовать много раз.

Switch в Java 12

В Java 12 были улучшены выражения Switch для сопоставления с образцом. Если использовать Switch как и в примере выше, для задания значения некоторой переменной мы должны были вычислить значение и присвоить заданной переменной, а затем использовать break:
int count = 2;
int value;
switch (count) {
  case 1:
     value = 12;
     break;
  case 2:
     value = 32;
     break;
  case 3:
     value = 52;
     break;
  default:
     value = 0;
}
Но благодаря возможностям 12-й версии Java мы можем переписать данное выражение следующим образом:
int value = switch (count) {
  case 1:
     break 12;
  case 2:
     break 32;
  case 3:
     break 52;
  default:
     break 0;
};
Давайте немного пройдемся по измененным моментам:
  1. Если ранее мы задавали переменной значение внутри блоков case, так как сам оператор switch не мог ничего возвращать, сейчас такая возможность у нас есть, и мы непосредственно с помощью switch возвращаем значение.

  2. Ранее справа от break у нас уже ничего не могло стоять, а сейчас мы его используем как оператор return для возвращения значения нашим switch. Метки с двоеточием отмечают точку входа в блок операторов. То есть с того места начинается выполнение всего кода ниже, даже тогда, когда встречается другая метка.

    Как итог, сквозной переход от метки к метке, который еще называют проваливанием (fall-through).

Проваливание (fall-through): выполнение идет от метки к метке без breakДля завершения такого прохода нужно либо полностью пройтись по всем элементам, либо использовать break или return. Нововведение в java 12 дает нам возможность использовать лямбда оператор, который в свою очередь гарантирует , что будет выполнен только код справа от нее. Без всякого "проваливания". Как будем выглядеть предыдущий пример в таком случае:
int count = 2;
int value = switch (count) {
  case 1 -> 12;
  case 2 -> 32;
  case 3 -> 52;
  default -> 0;
};
Код стал значительно проще, не правда ли? И еще: лямбда оператор может служить и типичным аналогом двоеточия, после которого идет целый блок с некоторыми операциями:
int count = 2;
int value = switch (count) {
  case 1 -> {
     //некоторые вычислительные операции...
     break 12;
  }
  case 2 -> {
     //некоторые вычислительные операции...
     break 32;
  }
  case 3 -> {
     //некоторые вычислительные операции...
     break 52;
  }
  default -> {
     //некоторые вычислительные операции...
     break 0;
  }
};
Ну а что если у нас для некоторых кейсов возвращаемое значение будет одинаковым? Получится, что у нас фактически одинаковые кейсы для некоторых разных значений. Как бы это можно было бы сократить с помощью новых возможностей Java 12:
int count = 2;
int value = switch (count) {
  case 1, 3, 5 -> 12;
  case 2, 4, 6 -> 52;
  default -> 0;
};

Switch в Java 13

В Java 13 изменился способ возврата значения из switch. Если в java 12 возвращаемое значение мы писали после break, который служил у нас как return для блока switch, то сейчас возвращать значение мы будем с помощью слова yield. Смотрим:
int value = switch (count) {
  case 1:
     yield 12;
  case 2:
     yield 32;
  case 3:
     yield 52;
  default:
     yield 0;
};
В тоже время, код, написанный на java 12 c использованием break для возврата, компилироваться не будет(( В switch-выражении значение возвращают через yield, а break без значения завершает switchBreak будет использоваться, но в тех ситуациях, когда нам не нужно ничего возвращать.

Итого

  • Используйте оператор case при числе ветвлений более двух, чтобы не загромождать if-структурами код.
  • Не забывайте завершать логический блок каждой ветки соответствующего конкретному значению (блок case) вызовом break.
  • Оператор switch помимо некоторых примитивных типов, в качестве выражения может использовать также типы Enum и String.
  • Помните про блок default, употребляйте его для обработки незапланированных значений выбора.
  • Для оптимизации производительности переместите ветки кода с наиболее часто встречающимися вариантами выбора к началу блока switch.
  • Не увлекайтесь «оптимизацией» за счет удаления break в конце блока выбора case, такой код сложен для понимания, и, как следствие, тяжело сопровождать при его развитии.
Полное описание оператора есть в документации Oracle (The switch Statement).

Читайте также

Вопросы и ответы

Что такое оператор switch в Java?

Это оператор множественного выбора: он вычисляет выражение и сравнивает его с вариантами case, выполняя код совпавшего варианта. Удобен как замена длинной цепочки if-else.

Когда использовать switch вместо if?

Когда веток больше двух и выбор идет по конкретному значению переменной. Для сложных логических условий или диапазонов лучше подходит if.

Какие типы можно использовать в switch?

byte, short, char, int, их обертки (Byte, Short, Character, Integer), String (с Java 7) и перечисления Enum.

Зачем нужен break в switch?

break завершает switch после выполнения нужного case. Без него выполнение «проваливается» в следующие case подряд (fall-through), что часто приводит к ошибкам.

Что такое проваливание (fall-through) в switch?

Это когда после совпавшего case, где нет break, выполняются все следующие case до конца switch или до первого break. Иногда используется намеренно (несколько case подряд), но чаще это ошибка.

Что нового в switch в новых версиях Java?

С Java 7 можно использовать String. С Java 12 появился стрелочный синтаксис case X -> без проваливания и switch как выражение. С Java 13 значение из switch возвращают через yield.
Комментарии (120)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
TimJohnzz
Уровень 23
15 сентября, 05:43
Вот почему бы не написать сразу послдений абзац текста, зачем обьяснять как было в доисторические времена, а потом писать, ну с java 13 break уже ничего возвращать не будет. я вот зачем читаю, про то что он может и возвращать, чтобы держать эту информацию ровно 2 минуты? :/
4aser Backend Developer
24 октября, 10:53
Понадобится в будущем на работе. В большинстве компаний java явно не последней версии, поэтому знать различия между разными версиями - не плохо
Grigoryvvv
Уровень 28
Expert
1 марта, 20:51
01.03.2026 / 14 уровень Лекция понравилась )
Руслан
Уровень 48
18 августа 2025, 22:35
Очень Крутая статья
Mikhail Savostin QA Automation Engineer
5 апреля 2025, 19:23
Спасибо!
Behzod KomilovYurist в BG GROUP COMPANY
21 ноября 2024, 06:48
Спасибо, полезная статья
Pallas's cat
Уровень 15
Expert
6 октября 2024, 22:41
Гарна стаття! Багато нової інформації, якої не було в лекціях.
SemperAnteBackend Developer в ItMatter
16 сентября 2024, 19:25
Вроде бы все хорошо, но разрешите докопаться!) "Для оптимизации производительности переместите ветки кода с наиболее часто встречающимися вариантами выбора к началу блока switch." - не совсем верное суждение, говорящее о не понимании как работает switch-case. Он из себя представляет "таблицу переходов", то есть, если не брать в рассмотрение новые (на 2024 год) switch-case с булевыми условиями (больше, меньше, ...), а брать именно константные свичи (которые в теме и приведены), то его сложность составляет О(1) - никак не зависит от количества лейблов. Совет же будет работать, только в случае если бы сложность была О(N). В качестве тестов можете сами прогнать if-else на эдак 1000 веток (лучше - больше) и switch на то же количество лейблов. Увидите, что с увеличением числа case, никак не меняется время работы switch. По сути как он работает: на стадии компиляции для наших "лейблов" вычисляется hashCode() и создается "таблица переходов" по этому коду. Далее в runtime при заходе в switch, вычисляется hashCode() переданного объекта и происходит прыжок на нужный label. Если его нет - прыжок в default. Если его нет - пропуск оператора, идем дальше. Таблица переходов сама работает за О(1). Я бы приложил пример кода + байт-кода, но ограничение по символам в комментах :(
Sergey Dubakin QA Automation Engineer Expert
29 апреля 2024, 05:52
Отличная статья, автор Молодец👏👏👏
Максим Li Backend Developer
4 декабря 2023, 16:36
Узнал много нового!
Кру
Уровень 22
25 ноября 2023, 10:37
я Ваш фанат! статьи такие понятные и информативные! спасибо!