W3docs

Оператор switch в Java

Оператор switch в Java: ветвление по значениям, метки case, break, default и сквозное выполнение.

Когда нужно сравнить одно значение с несколькими вариантами, длинная цепочка if/else if быстро становится громоздкой. Оператор switch — компактная альтернатива в Java: значение читается один раз, выполнение переходит к подходящему case и запускает его блок.

Базовый синтаксис

switch (value) {
  case label1:
    // body
    break;
  case label2:
    // body
    break;
  default:
    // body
    break;
}

Небольшой пример:

int day = 3;

switch (day) {
  case 1:
    System.out.println("Monday");
    break;
  case 2:
    System.out.println("Tuesday");
    break;
  case 3:
    System.out.println("Wednesday");
    break;
  default:
    System.out.println("Other");
    break;
}

Switch переходит к case 3:, печатает Wednesday, попадает на break и выходит.

Зачем нужен break

Без break выполнение проваливается в следующий case — даже если его метка не совпадает. Это намеренная особенность switch в стиле C, но именно она является источником бесчисленных ошибок в Java-коде:

switch (day) {
  case 1:
    System.out.println("Monday");
    // no break!
  case 2:
    System.out.println("Tuesday");
    break;
}

Когда day == 1, выводятся и Monday, и Tuesday. Всегда добавляйте break, если вы не хотите сквозного выполнения намеренно.

Намеренное сквозное выполнение

Иногда сквозное выполнение — именно то, что нужно: группировка нескольких меток под одним блоком:

switch (day) {
  case 1:
  case 2:
  case 3:
  case 4:
  case 5:
    System.out.println("Weekday");
    break;
  case 6:
  case 7:
    System.out.println("Weekend");
    break;
}

Когда вы делаете это намеренно, добавьте комментарий // fall through, чтобы ревьюеры не подумали, что вы забыли break. (Новый синтаксис switch-выражений — рассматривается в следующей главе — полностью устраняет эту проблему.)

Какие значения принимает switch?

Традиционный switch принимает:

  • Все целочисленные типы: byte, short, int, char
  • Их обёртки: Byte, Short, Integer, Character
  • String (начиная с Java 7)
  • Константы enum

Не допускаются: long, float, double, boolean и произвольные объекты. Для них используйте if/else.

String role = "admin";

switch (role) {
  case "admin":
    System.out.println("Full access");
    break;
  case "editor":
    System.out.println("Write access");
    break;
  case "viewer":
    System.out.println("Read access");
    break;
  default:
    System.out.println("No access");
    break;
}

Сравнение строк в switch использует семантику String.equals — с учётом регистра. Важный нюанс: переключение по String (или любому упакованному/enum значению), равному null, выбрасывает NullPointerException. Проверяйте null перед switch или обрабатывайте его в условии:

if (role == null) {
  System.out.println("No role");
} else {
  switch (role) {
    case "admin":
      System.out.println("Full access");
      break;
    // ...
  }
}

default — ветвь по умолчанию

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

default не обязан быть последним. По соглашению он размещается внизу, но компилятор принимает его в любом месте — при отсутствии break выполнение проваливается через него так же, как через любой другой case.

Важные правила

Несколько правил, применяемых компилятором, часто вызывают затруднения:

  • Метки case должны быть константами времени компиляции. Можно использовать литералы (case 3:), константы final или имена enum — но не переменные и не вызовы методов. case x:, где x — не-final переменная, не скомпилируется.
  • Метки должны быть уникальными. Два case 3: в одном switch — ошибка компиляции.
  • Все case разделяют одну область видимости. Переменная, объявленная в одном case, видна в других, что может привести к конфликтам. Оборачивайте тело case в фигурные скобки { }, когда вам нужна локальная переменная только для этого case:
switch (day) {
  case 1: {
    int hours = 8;
    System.out.println(hours);
    break;
  }
  case 2:
    // `hours` is not visible here
    break;
}

Switch с enum

enum и switch — естественная пара. Внутри switch по значению enum не нужно квалифицировать имя константы:

enum Status { PENDING, ACTIVE, DONE }

Status s = Status.ACTIVE;

switch (s) {
  case PENDING:           // not Status.PENDING
    System.out.println("Waiting...");
    break;
  case ACTIVE:
    System.out.println("In progress");
    break;
  case DONE:
    System.out.println("Finished");
    break;
}

Практический пример

java— editable, runs on the server

Что дальше

В Java 14 были введены switch-выражения, которые возвращают значение, устраняют сквозное выполнение и поддерживают несколько меток в одном case — современный Java-код предпочитает их всякий раз, когда целевая версия — Java 14 или выше.

Практика

Практика
В традиционном switch Java что произойдёт, если опустить break в блоке case?
В традиционном switch Java что произойдёт, если опустить break в блоке case?
Was this page helpful?