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