Код
#статьи

Оператор switch в Java: описание, эволюция и примеры использования

Чтобы выполнять разные блоки кода в зависимости от условий, разработчики изобрели if-else. А затем ещё подумали и создали switch. Разбираемся зачем 🤔

Иллюстрация: Оля Ежак для Skillbox Media

Язык программирования Java появился в 1995 году и с тех пор претерпел множество изменений. Одним из значительных улучшений стал оператор switch, который позволяет обрабатывать различные случаи (cases) в зависимости от значения переменной. Представьте, что вы заказываете пиццу через приложение и можете выбрать только её размер:

  • Маленькая пицца с пеперони — 500 рублей.
  • Средняя пицца с ветчиной и грибами — 750 рублей.
  • Большая пицца с морепродуктами — 1000 рублей.

В этом примере от размера пиццы зависит её цена и начинка. У оператора switch похожая логика: он помогает программам принимать решения и отображать разную информацию в зависимости от конкретного значения.

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

Содержание

Оператор switch в Java: синтаксис и примеры реализации

Оператор switch — это конструкция с несколькими условиями, каждое из которых можно поочерёдно сравнивать со значением переменной. После сравнения активируется только то условие, которое соответствует значению переменной. Его форма записи выглядит следующим образом:

switch (variable) {
    case value1:
        // Если переменная равна value1, то выполнится этот код
        break;
    case value2:
        // Если переменная равна value2, выполнится этот код
        break;
    ...
    default:
        // Если ни одно из значений не совпало, то выполнится этот код
}

Расшифруем синтаксис:

  • Ключевое слово switch — это сам оператор, позволяющий выбрать один из нескольких блоков кода на основе значения переменной.
  • Переменная variable — это имя переменной, которое мы указываем в круглых скобках и сравниваем с блоками кода внутри оператора.
  • Блоки case содержат возможные значения переменной и код, который выполнится в случае совпадения с исходным условием. Количество блоков case может быть неограниченным, а внутри каждого блока могут находиться любые операторы или выражения.
  • Оператор break останавливает проверку и срабатывает в ситуациях, когда значение переменной совпадает с одним из блоков case. Если не указать break, то программа продолжит анализировать последующие блоки, пока не проверит их все и не достигнет конца.
  • Ключевое слово default — это блок кода на случай, если ни одно из значений в блоках case не совпадёт с переменной.

В начале статьи мы в общем виде рассматривали пример с пиццей. Теперь, когда вы познакомились с синтаксисом, оформим этот пример в виде кода:

String pizzaSize = "большая"; // Создаём переменную и задаём ей значение 
int price; // Создаём переменную для хранения цены пиццы

switch (pizzaSize) {
    case "маленькая": // Первое условие: если размер пиццы маленький
        price = 500; // Устанавливаем цену 500 рублей
        break; // Завершаем выполнение switch
    case "средняя": // Второе условие: если размер пиццы средний
        price = 750; // Устанавливаем цену 750 рублей
        break; // Завершаем выполнение switch
    case "большая": // Третье условие: если размер пиццы большой
        price = 1000; // Устанавливаем цену 1000 рублей
        break; // Завершаем выполнение switch
    default: // Если размер пиццы не распознан
        price = 0; // Устанавливаем цену 0 для некорректного размера
        System.out.println("Неизвестный размер пиццы"); // Выводим сообщение об ошибке
}

System.out.println("Цена пиццы: " + price + " рублей"); // Выводим цену пиццы

Закрепим материал на другом примере. Возьмём меню консольной игры и попросим пользователя ввести цифру для определённого действия: 1 — начать игру, 2 — перейти в настройки, 3 — выйти из игры.

Для начала создадим объект Scanner, который позволит пользователю ввести цифру в консоли:

// Импортируем класс java.util.Scanner для работы с пользовательским вводом
import java.util.Scanner;

public class Main { // Указываем название класса
   public static void main(String[] args) { // Добавляем главный метод программы
       // Создаём объект Scanner для считывания пользовательского ввода
       Scanner input = new Scanner(System.in);

       // Сохраняем в переменную цифру, которую введёт пользователь
       int inputValue = input.nextInt(); 

       // Закрываем объект Scanner после использования, чтобы избежать утечек ресурсов
       input.close();
   }
}

Теперь проверим значение переменной inputValue и выполним действие в зависимости от того, какую цифру ввёл пользователь:

switch (inputValue) {
   case 1:
       System.out.println("Начинаем игру");
       break;
   case 2:
       System.out.println("Переходим в настройки");
       break;
   case 3:
       System.out.println("Выходим из игры");
       break;
   default:
       System.out.println("Ошибка ввода. Пожалуйста, введите цифру 1, 2 или 3 и повторите попытку."); // Сообщение об ошибке ввода
       break;
}

Когда пользователь введёт одну из цифр, оператор switch начнёт сравнивать значение переменной inputValue с числами в блоках case. Если одно из значений совпадёт, выполнится соответствующий код; если нет, сработает код в блоке default. Каждый блок case завершается оператором break, который предотвращает выполнение следующего блока.

В конструкции switch можно не использовать операторы default и break. Однако без default программа не сможет выполнить никаких действий, если пользователь введёт некорректное значение. А если не использовать break, то компилятор продолжит выполнение кода в следующих case и это может привести к неожиданным результатам. Разберём это на примере:

switch (inputValue) {
    case 1:
        System.out.println("Начинаем игру");
    case 2:
        System.out.println("Переходим в настройки");
    case 3:
        System.out.println("Выходим из игры");
    default:
        System.out.println("Ошибка ввода. Пожалуйста, введите цифру 1, 2 или 3"); 
}

Теперь, если пользователь введёт цифру 1, 2 или 3, то получит следующее:

Начинаем игру
Переходим в настройки
Выходим из игры
Ошибка ввода. Пожалуйста, введите цифру 1, 2 или 3

Без операторов break программа выполнит все блоки кода в каждом case, пока не дойдёт до конца конструкции switch. Если пользователь введёт цифру 4 или другое непредусмотренное значение, консоль останется пустой — без блока default программа не знает, как обрабатывать такие случаи.

Сравнение операторов if-else и switch

Оператор switch часто сравнивают с условной инструкцией if-else, так как обе конструкции помогают программе выполнять различные действия в зависимости от условий:

  • if-else проверяет одно или несколько условий, и, если они истинны, выполняется код в блоке if; если нет — срабатывает else.
  • switch проверяет значение переменной и сравнивает его с возможными вариантами в блоках case.

Также у этих операторов похожая структура:

  • В if-else можно использовать несколько последовательных условий и логические операторы.
  • В switch можно указать множество блоков case, соответствующих определённым значениям.

Ещё у них есть обработка неучтённых случаев:

  • В конструкции if-else выполнится блок else, если среди условий не будет ни одного истинного.
  • В операторе switch аналогом else выступает блок default, и он выполнится, если ни одно значение не совпадает с указанными case.

Оба оператора позволяют контролировать поток программы и выполнять разные действия в зависимости от заданных условий. Перепишем пример с меню консольной игры, используя конструкцию if-else. Этот код выполняет ту же функцию, что и switch, и даже выглядит похожим образом:

int inputValue = 2; // Предположим, пользователь ввёл 2

if (inputValue == 1) {
    System.out.println("Начинаем игру");
} else if (inputValue == 2) {
    System.out.println("Переходим в настройки");
} else if (inputValue == 3) {
    System.out.println("Выходим из игры");
} else {
    System.out.println("Ошибка ввода. Пожалуйста, введите цифру 1, 2 или 3.");
}

На простых примерах различия между switch и if-else незаметны, и разработчик может выбирать между этими конструкциями по своему усмотрению. Однако конструкция if-else лучше подходит для сложных логических проверок и ситуаций, когда необходимо использовать диапазоны значений. А вот switch чаще применяется для сравнения одного значения с множеством фиксированных значений.

Предположим, нам нужно проверить число и определить, является оно положительным, отрицательным или нулём. Оператор switch не сможет выполнить такую проверку, поскольку не работает с диапазонами значений и не поддерживает логические условия, такие как «больше нуля» или «меньше нуля». Поэтому нам удобно использовать конструкцию if-else:

int number = -5; // Предположим, пользователь ввёл -5

if (number > 0) {
    System.out.println("Число положительное");
} else if (number < 0) {
    System.out.println("Число отрицательное");
} else {
    System.out.println("Число равно нулю");
}

А теперь рассмотрим другую ситуацию, где нам нужно определить день недели по его номеру: 1 — это понедельник, 2 — вторник и так далее. В этом случае мы сравниваем значение переменной с множеством фиксированных значений, и для этого лучше подходит оператор switch:

int day = 3; // Предположим, пользователь ввёл 3

switch (day) {
    case 1:
        System.out.println("Понедельник");
        break;
    case 2:
        System.out.println("Вторник");
        break;
    case 3:
        System.out.println("Среда");
        break;
    case 4:
        System.out.println("Четверг");
        break;
    case 5:
        System.out.println("Пятница");
        break;
    case 6:
        System.out.println("Суббота");
        break;
    case 7:
        System.out.println("Воскресенье");
        break;
    default:
        System.out.println("Ошибка ввода. Введите число от 1 до 7.");
        break;
}

Мы можем переписать этот пример с использованием if-else, однако код станет громоздким и менее читаемым. И чем больше подобных значений мы сравниваем, тем заметнее будет становиться разница:

int day = 3; // Предположим, пользователь ввёл 3

if (day == 1) {
    System.out.println("Понедельник");
} else if (day == 2) {
    System.out.println("Вторник");
} else if (day == 3) {
    System.out.println("Среда");
} else if (day == 4) {
    System.out.println("Четверг");
} else if (day == 5) {
    System.out.println("Пятница");
} else if (day == 6) {
    System.out.println("Суббота");
} else if (day == 7) {
    System.out.println("Воскресенье");
} else {
    System.out.println("Ошибка ввода. Введите число от 1 до 7.");
}

Эволюция оператора switch

Конструкция switch существует с момента появления языка Java, и с выходом новых версий она претерпела несколько модификаций. Ключевые обновления произошли в Java 7, 12 и 13. В остальных версиях изменения были незначительными, и мы можем проследить развитие оператора.

Switch в Java 7: появилась поддержка строк

До Java 7 оператор switch поддерживал ограниченный набор типов данных. Сначала это были только примитивные типы: byte, short, char и int. С выходом Java 5 к этим типам добавилась поддержка перечислений (enum) и соответствующих классов-обёрток: Byte, Short, Character и Integer.

Создадим перечисление с тремя именованными константами для представления различных цветов:

public enum Color {
    RED, BLUE, GREEN
}

Теперь мы можем использовать перечисление Color в операторе switch для сравнения значений:

Color color = Color.BLUE; // Создаём переменную color и присваиваем ей значение BLUE

switch (color) {
    case RED:
        System.out.println("Красный"); // Если color равно RED, выводим «Красный»
        break;
    case BLUE:
        System.out.println("Синий"); // Если color равно BLUE, выводим «Синий»
        break;
    case GREEN:
        System.out.println("Зелёный"); // Если color равно GREEN, выводим «Зелёный»
        break;
}

В нашем примере переменная color хранит значение Color.BLUE. При выполнении оператора switch программа сравнивает значение переменной color с каждым из case и выполняет соответствующий код. В данном случае в консоли выведется «Синий», так как значение color равно BLUE.

Начиная с Java 7, оператор switch поддерживает строковый тип данных — String. Это значительно упростило использование оператора, поскольку теперь вместо перечислений мы можем просто задать цвет в виде строки:

String colorName = "Blue"; // Создаём переменную colorName и присваиваем ей строковое значение Blue

switch(colorName) {
    case "Red": // Если colorName равно Red
        System.out.println("Красный"); // Выводим «Красный»
        break; 
    case "Blue": // Если colorName равно Blue
        System.out.println("Синий"); // Выводим «Синий»
        break; 
    case "Green": // Если colorName равно Green
        System.out.println("Зелёный"); // Выводим «Зелёный»
        break; 
}

Switch в Java 12: оператор стал выражением и получил поддержку множественных case

С 2019 года оператор switch превратился в выражение и научился не просто выполнять действия в зависимости от переменной, но и возвращать значения. До обновления можно было возвращать значения через return:

int variable = 0;

switch (variable) {
   case 0: return false;
   case 1: return true;
}

С выходом Java 12 мы можем возвращать значение из case с помощью оператора -> и присваивать его переменной:

// Создаём переменную value и присваиваем ей результат выполнения switch
boolean value = switch (variable) {
   case 0 -> false; // Если variable равно 0, возвращаем false
   case 1 -> true;  // Если variable равно 1, возвращаем true
};

Если нам не нужно возвращать значение из выражения, то мы можем не использовать оператор break в конце каждого case:

switch (variable) {
   case 0 -> System.out.println("Ноль"); // Выводим «Ноль», если переменная равна 0
   case 1 -> System.out.println("Один");  // Выводим «Один», если переменная равна 1
   default -> System.out.println("Ошибка"); // Выводим «Ошибка» для остальных значений
}

Также в Java 12 появился множественный case. Возьмём вот такой пример:

switch(num) {
   case 1:
   case 2:
   case 3: 
       System.out.println("Это число от 1 до 3"); 
       break;
   case 4:
   case 5:
   case 6: 
       System.out.println("Это число от 4 до 6"); 
       break;
}

Теперь вместо нескольких case мы можем объединить условия через запятую, использовать оператор ->, отказаться от break и сократить код:

switch(num) {
   case 1, 2, 3 -> System.out.println("Это число от 1 до 3"); // Выводим сообщение для чисел 1, 2 и 3
   case 4, 5, 6 -> System.out.println("Это число от 4 до 6"); // Выводим сообщение для чисел 4, 5 и 6
   default -> System.out.println("Ошибка"); // Выводим «Ошибка» для остальных значений
}

Switch в Java 13: оператор yield заменили на break

В Java 12 появилась возможность возвращать значения прямо из кейса с использованием оператора break. Также этот оператор использовался для завершения выполнения блока в ситуациях, когда необходимо было остановить выполнение switch и перейти к следующему после него коду:

int variable = 0;

String value = switch(variable) {
    case 0 -> {
        System.out.println("Число 0");
        break "Zero"; // Возвращаем Zero для переменной 0
    }
    case 1 -> {
        System.out.println("Число 1");
        break "One"; // Возвращаем One для переменной 1
    }
    default -> {
        System.out.println("Другое число");
        break "Error"; // Возвращаем Error для остальных значений
    }
};

Двойное назначение оператора break вызывало путаницу, и в Java 13 его заменили на yield. Теперь новый оператор выполняет функцию оператора return, а break используется для завершения выполнения блока в switch:

int variable = 0;

String value = switch(variable) {
    case 0 -> {
        System.out.println("Число 0");
        yield "Zero"; // Возвращаем Zero для переменной 0
    }
    case 1 -> {
        System.out.println("Число 1");
        yield "One"; // Возвращаем One для переменной 1
    }
    default -> {
        System.out.println("Другое число");
        yield "Error"; // Возвращаем Error для остальных значений
    }
};

Больше интересного про код — в нашем телеграм-канале. Подписывайтесь!

Изучайте IT на практике — бесплатно

Курсы за 2990 0 р.

Я не знаю, с чего начать
Научитесь: Профессия Java-разработчик Узнать больше
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована