Найти в Дзене
Concepta junior

Switch в Java: от простого к крутому

Привет! Ты когда-нибудь играл в игру, где нужно выбирать разные пути в зависимости от ситуации? Например, если идёт дождь - берём зонт, если солнечно - надеваем кепку, а если облачно - просто идём гулять. В программировании такие ситуации встречаются постоянно, и специально для них существует конструкция switch! Switch - это как волшебный переключатель в твоём коде, который помогает выбрать нужное действие в зависимости от значения какой-то переменной. Раньше switch в Java выглядел примерно так: java// Определяем сезон по номеру месяца
int месяц = 7;
String сезон;
switch (месяц) {
case 12:
case 1:
case 2:
сезон = "Зима";
break;
case 3:
case 4:
case 5:
сезон = "Весна";
break;
case 6:
case 7:
case 8:
сезон = "Лето";
break;
case 9:
case 10:
case 11:
сезон = "Осень";
break;
default:
сезон = "Неизвестный месяц";
break;
}
System.out.println("Сейчас " + сезон);
Оглавление

Что такое switch и зачем он нужен?

Привет! Ты когда-нибудь играл в игру, где нужно выбирать разные пути в зависимости от ситуации? Например, если идёт дождь - берём зонт, если солнечно - надеваем кепку, а если облачно - просто идём гулять. В программировании такие ситуации встречаются постоянно, и специально для них существует конструкция switch!

Switch - это как волшебный переключатель в твоём коде, который помогает выбрать нужное действие в зависимости от значения какой-то переменной.

Старый добрый switch (до Java 12)

Раньше switch в Java выглядел примерно так:

java// Определяем сезон по номеру месяца
int месяц = 7;
String сезон;

switch (месяц) {
case 12:
case 1:
case 2:
сезон = "Зима";
break;
case 3:
case 4:
case 5:
сезон = "Весна";
break;
case 6:
case 7:
case 8:
сезон = "Лето";
break;
case 9:
case 10:
case 11:
сезон = "Осень";
break;
default:
сезон = "Неизвестный месяц";
break;
}

System.out.println("Сейчас " + сезон);

Этот код определяет, к какому сезону относится месяц. Но в нём есть несколько проблем:

  1. Легко забыть break - если ты забудешь написать break, код "провалится" в следующий case, что может вызвать неожиданное поведение.
  2. Нельзя сразу присвоить результат переменной - приходится создавать временную переменную сезон.
  3. Громоздкий синтаксис - много лишних слов и повторений.

Проблемы старого switch

Давай посмотрим на ещё один пример, который показывает все недостатки старого switch:

java// Перевод оценки из числа в букву
enum Оценка { ОТЛИЧНО, ХОРОШО, УДОВЛЕТВОРИТЕЛЬНО, НЕУД }

Оценка оценка = Оценка.ХОРОШО;
String буква;

switch (оценка) {
case ОТЛИЧНО:
буква = "A";
break;
case ХОРОШО:
буква = "B";
break;
case УДОВЛЕТВОРИТЕЛЬНО:
буква = "C";
break;
case НЕУД:
буква = "F";
break;
default:
// Непонятно, зачем здесь default, если мы перечислили все возможные оценки
буква = "?";
break;
}

В этом коде есть несколько недостатков:

  • Мы вынуждены использовать временную переменную буква
  • Нам приходится писать break после каждого case
  • Компилятор не подскажет, если мы забудем обработать какой-то тип оценки
  • В разных case нельзя создать переменные с одинаковым именем

Новый крутой switch (начиная с Java 12)

Начиная с Java 12, switch стал намного круче! Теперь он может быть выражением, а не только оператором. Это значит, что switch может возвращать значение, которое можно сразу присвоить переменной:

java// Тот же пример с сезонами, но с новым switch
int месяц = 7;
String сезон = switch (месяц) {
case 12, 1, 2 -> "Зима";
case 3, 4, 5 -> "Весна";
case 6, 7, 8 -> "Лето";
case 9, 10, 11 -> "Осень";
default -> "Неизвестный месяц";
};

System.out.println("Сейчас " + сезон);

Видишь, как круто?

  • Никаких break!
  • Сразу присваиваем результат переменной
  • Несколько значений в одном case через запятую
  • Стрелка -> вместо двоеточия : делает код чище

Стрелки вместо двоеточий

Новый switch может использовать стрелки -> вместо двоеточий :. В чём разница?

  1. Стрелка ->: выполняется только код справа от стрелки, никакого "проваливания" в следующий case
  2. Двоеточие :: старое поведение с "проваливанием" в следующий case, если нет break

Даже со старым синтаксисом через двоеточие, в новом switch можно использовать ключевое слово yield для возврата значения:

javaString буква = switch (оценка) {
case ОТЛИЧНО:
yield "A";
case ХОРОШО:
yield "B";
case УДОВЛЕТВОРИТЕЛЬНО:
yield "C";
case НЕУД:
yield "F";
default:
yield "?";
};

Блоки кода в switch

Если тебе нужно выполнить несколько строк кода в одном case, можно использовать фигурные скобки:

javaString сообщение = switch (оценка) {
case ОТЛИЧНО -> {
System.out.println("Поздравляю!");
yield "Ты получил отличную оценку!";
}
case ХОРОШО -> {
System.out.println("Неплохо!");
yield "Ты хорошо справился!";
}
case УДОВЛЕТВОРИТЕЛЬНО -> {
System.out.println("Можно лучше!");
yield "Ты справился, но есть куда расти!";
}
case НЕУД -> {
System.out.println("Ой-ой!");
yield "Нужно больше заниматься!";
}
};

Обрати внимание на слово yield - оно используется для возврата значения из блока. Это не то же самое, что return, который выходит из всего метода.

Полезная особенность: компилятор проверяет все значения Enum

Если ты используешь switch с enum (перечислением), компилятор может проверить, обработал ли ты все возможные значения:

javaenum Светофор { КРАСНЫЙ, ЖЕЛТЫЙ, ЗЕЛЕНЫЙ }

String действие = switch (светофор) {
case КРАСНЫЙ -> "Стой!";
case ЖЕЛТЫЙ -> "Готовься!";
case ЗЕЛЕНЫЙ -> "Иди!";
// Здесь нет default, но код компилируется,
// потому что мы обработали все возможные значения Светофора
};

Если в будущем кто-то добавит новое значение в enum (например, МИГАЮЩИЙ_ЖЕЛТЫЙ), компилятор выдаст ошибку, напоминая тебе, что нужно обработать и этот случай. Это очень удобно!

Использование паттернов типов (Java 17+)

Начиная с Java 17, switch может проверять не только значение, но и тип переменной:

javaObject объект = "Привет, мир!";

String результат = switch (объект) {
case String текст -> "Это строка: " + текст;
case Integer число -> "Это число: " + число;
case Double дробь -> "Это дробное число: " + дробь;
default -> "Это что-то другое";
};

System.out.println(результат);
// Выведет: "Это строка: Привет, мир!"

Это называется "паттерны типов" в switch, и это очень мощная возможность!

Практический пример: игра "Камень, ножницы, бумага"

Давай создадим простую игру с использованием новых возможностей switch:

javaimport java.util.Random;
import java.util.Scanner;

public class КаменьНожницыБумага {
enum Выбор { КАМЕНЬ, НОЖНИЦЫ, БУМАГА }

public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Random random = new Random();

System.out.println("Выбери: 1 - Камень, 2 - Ножницы, 3 - Бумага");
int выборИгрока = scanner.nextInt();

// Преобразуем число в enum
Выбор игрок = switch (выборИгрока) {
case 1 -> Выбор.КАМЕНЬ;
case 2 -> Выбор.НОЖНИЦЫ;
case 3 -> Выбор.БУМАГА;
default -> {
System.out.println("Неверный выбор! Я выбрал за тебя Камень.");
yield Выбор.КАМЕНЬ;
}
};

// Компьютер делает случайный выбор
Выбор компьютер = Выбор.values()[random.nextInt(3)];

System.out.println("Ты выбрал: " + игрок);
System.out.println("Компьютер выбрал: " + компьютер);

// Определяем победителя с помощью нового switch
String результат = switch (игрок) {
case КАМЕНЬ -> switch (компьютер) {
case КАМЕНЬ -> "Ничья!";
case НОЖНИЦЫ -> "Ты победил!";
case БУМАГА -> "Компьютер победил!";
};
case НОЖНИЦЫ -> switch (компьютер) {
case КАМЕНЬ -> "Компьютер победил!";
case НОЖНИЦЫ -> "Ничья!";
case БУМАГА -> "Ты победил!";
};
case БУМАГА -> switch (компьютер) {
case КАМЕНЬ -> "Ты победил!";
case НОЖНИЦЫ -> "Компьютер победил!";
case БУМАГА -> "Ничья!";
};
};

System.out.println(результат);
}
}

Обрати внимание, как мы использовали вложенный switch! Это один из способов сравнить два значения.

Советы по использованию switch в современной Java

  1. Используй стрелки -> вместо двоеточий : - это избавит тебя от проблем с "проваливанием" и забытыми break.
  2. Используй switch как выражение, когда нужно вычислить и присвоить значение:
    javaString сообщение = switch (день) {
    case ПОНЕДЕЛЬНИК -> "Начало недели";
    case ПЯТНИЦА -> "Скоро выходные!";
    default -> "Обычный день";
    };
  3. Для enum не используй default, если обработал все значения. Это поможет компилятору предупредить тебя, если добавится новое значение.
  4. Используй несколько меток для одного case через запятую:
    javaString рабочийДень = switch (день) {
    case ПОНЕДЕЛЬНИК, ВТОРНИК, СРЕДА, ЧЕТВЕРГ, ПЯТНИЦА -> "Да";
    case СУББОТА, ВОСКРЕСЕНЬЕ -> "Нет";
    };
  5. Для сложной логики используй блоки и yield:
    javaString результат = switch (число) {
    case 1 -> "Один";
    case 2 -> {
    int квадрат = число * число;
    yield "Два в квадрате: " + квадрат;
    }
    default -> "Другое число";
    };

Switch в Java стал намного мощнее и удобнее с Java 12 и продолжает улучшаться! Теперь ты знаешь:

  • Как использовать switch как выражение
  • Как применять стрелки -> вместо двоеточий :
  • Как обойтись без break
  • Как проверять типы переменных (с Java 17+)
  • Как правильно работать с enum

Эти знания сделают твой код чище, короче и безопаснее. Удачи в программировании! 🚀