Это супер-быстрый гид по switchвыражениям Java 12/13 . Узнайте, как использовать switch выражения за 5 минут.
Вам также может понравиться: JDK 12: Переключение операторов / выражений в действии
Старый школьный коммутатор
Прежде чем мы кратко рассмотрим switchвыражения, представленные в JDK 12, давайте рассмотрим типичный пример старой школы, заключенный в метод ( PlayerTypesэто простая Java enum).
Джава
1
private static Player createPlayer(PlayerTypes playerType) {
2
3
switch (playerType) {
4
case TENNIS:
5
return new TennisPlayer();
6
case FOOTBALL:
7
return new FootballPlayer();
8
case SNOOKER:
9
return new SnookerPlayer();
10
case UNKNOWN:
11
throw new UnknownPlayerException("Player type is unknown");
12
13
default:
14
throw new IllegalArgumentException(
15
"Invalid player type: " + playerType);
16
}
17
}
Если мы забудем о
default, то код не скомпилируется.
Предыдущий пример приемлем. В худшем случае мы можем добавить ложную переменную (например, player), некоторые беспорядочные break операторы и не получать жалоб, если их defaultне хватает. Итак, следующий код — старая школа, очень уродливаяswitch.
Джава
xxxxxxxxxx
1
private static Player createPlayerSwitch(PlayerTypes playerType) {
2
3
Player player = null;
4
switch (playerType) {
5
case TENNIS:
6
player = new TennisPlayer();
7
break;
8
case FOOTBALL:
9
player = new FootballPlayer();
10
break;
11
case SNOOKER:
12
player = new SnookerPlayer();
13
break;
14
case UNKNOWN:
15
throw new UnknownPlayerException(
16
"Player type is unknown");
17
18
default:
19
throw new IllegalArgumentException(
20
"Invalid player type: " + playerType);
21
}
22
23
return player;
24
}
Если мы забудем о том default, то не будет никаких претензий со стороны компилятора. В этом случае пропущенный default случай может привести к nullигроку.
Выражение переключателя Java 12
Однако, начиная с JDK 12 , мы можем полагаться на switch выражения. До JDK 12 switch был оператор, конструкция, предназначенная для управления потоком (например, как if оператор) без представления результата. С другой стороны, выражение оценивается как результат. Следовательно, switch выражение может иметь результат.
Предыдущее switch выражение старой школы может быть написано в стиле JDK 12 следующим образом.
Джава
xxxxxxxxxx
1
private static Player createPlayer(PlayerTypes playerType) {
2
3
return switch (playerType) {
4
case TENNIS -> new TennisPlayer();
5
case FOOTBALL -> new FootballPlayer();
6
case SNOOKER -> new SnookerPlayer();
7
case UNKNOWN -> throw new UnknownPlayerException(
8
"Player type is unknown");
9
10
// default is not mandatory
11
default -> throw new IllegalArgumentException(
12
"Invalid player type: " + playerType);
13
};
14
}
На этот раз
defaultне обязательно. Мы можем пропустить это.
JDK 12 switchдостаточно умен, чтобы сигнализировать, если switchне охватывает все возможные входные значения. Это очень полезно в случае enum значений Java . JDK 12 switch может определить, все ли значения перечисления покрыты, и не вызывать бесполезного, defaultесли это не так. Например, если мы удалим default и добавим новую запись в PlayerTypes enum (например, GOLF), то компилятор сообщит об этом через сообщение, как на следующем снимке экрана (это из NetBeans).
Обратите внимание, что между меткой и выполнением мы заменили двоеточие стрелкой (синтаксис в стиле лямбды). Основная роль этой стрелки — предотвратить провал, а это означает, что будет выполнен только блок кода справа. Там нет необходимости использовать break.
Не думайте, что стрелка превращает switch оператор в switch выражение. switch Выражение может быть использовано с двоеточием , а break также, следующим образом :
Джава
xxxxxxxxxx
1
private static Player createPlayer(PlayerTypes playerType) {
2
3
return switch (playerType) {
4
case TENNIS: break new TennisPlayer();
5
case FOOTBALL: break new FootballPlayer();
6
case SNOOKER: break new SnookerPlayer();
7
case UNKNOWN: throw new UnknownPlayerException(
8
"Player type is unknown");
9
10
// default is not mandatory
11
default: throw new IllegalArgumentException(
12
"Invalid player type: " + playerType);
13
};
14
}
Наш пример сообщение
switchчерезenum, но JDK 12switchтакже может быть использовано в течениеint,Integer,short,Short,byte,Byte,char,Character, иString.Обратите внимание, что JDK 12 приносит
switchвыражения в качестве функции предварительного просмотра. Это означает, что он подвержен изменениям в следующих нескольких выпусках, и его необходимо разблокировать с помощью--enablepreview command-lineпараметра при компиляции и времени выполнения.
Полный пример доступен на GitHub .
Несколько кейсов
До JDK 12 switch оператор допускал одну метку для case. Начиная с switch выражений, a case может иметь несколько меток, разделенных запятой. Проверьте следующий метод, который иллюстрирует несколько case меток:
Джава
xxxxxxxxxx
1
private static SportType fetchSportTypeByPlayerType(PlayerTypes playerType) {
2
3
return switch (playerType) {
4
case TENNIS, GOLF, SNOOKER -> new Individual();
5
case FOOTBALL, VOLLEY -> new Team();
6
};
7
}
Если мы перейдем к этому методу TENNIS, GOLFили SNOOKER, он вернет экземпляр Individual класса. Если мы передадим FOOTBALL или VOLLEY, он вернет экземпляр Team класса.
Полный пример доступен на GitHub .
Блоки заявления
Стрелка метки может указывать на один оператор (как в примерах из предыдущих двух примеров) или блок с фигурными скобками. Это очень похоже на лямбда-блоки. Проверьте следующее решение:
Джава
xxxxxxxxxx
1
private static Player createPlayer(PlayerTypes playerType) {
2
3
return switch (playerType) {
4
case TENNIS -> {
5
System.out.println("Creating a TennisPlayer ...");
6
break new TennisPlayer();
7
}
8
case FOOTBALL -> {
9
System.out.println("Creating a FootballPlayer ...");
10
break new FootballPlayer();
11
}
12
case SNOOKER -> {
13
System.out.println("Creating a SnookerPlayer ...");
14
break new SnookerPlayer();
15
}
16
17
default -> throw new IllegalArgumentException(
18
"Invalid player type: " + playerType);
19
};
20
}
Обратите внимание, что мы выходим из фигурного блока через break, а не return. Другими словами, хотя мы можем return изнутри switch выражения, мы не можем return изнутри выражения.
Полный пример доступен на GitHub .
Выражения коммутатора Java 13
Однако, начиная с JDK 13 , break оператор with со значением отбрасывается в пользу yieldоператора. Остальное остается прежним. Итак, используя yieldмы получаем:
Джава
xxxxxxxxxx
1
private static Player createPlayer(PlayerTypes playerType) {
2
3
return switch (playerType) {
4
case TENNIS: yield new TennisPlayer();
5
case FOOTBALL: yield new FootballPlayer();
6
case SNOOKER: yield new SnookerPlayer();
7
case UNKNOWN: throw new UnknownPlayerException(
8
"Player type is unknown");
9
10
// default is not mandatory
11
default: throw new IllegalArgumentException(
12
"Invalid player type: " + playerType);
13
};
14
}
Полный пример доступен на GitHub .
Мы также получаем:
Джава
xxxxxxxxxx
1
private static Player createPlayer(PlayerTypes playerType) {
2
3
return switch (playerType) {
4
case TENNIS -> {
5
System.out.println("Creating a TennisPlayer ...");
6
yield new TennisPlayer();
7
}
8
case FOOTBALL -> {
9
System.out.println("Creating a FootballPlayer ...");
10
yield new FootballPlayer();
11
}
12
case SNOOKER -> {
13
System.out.println("Creating a SnookerPlayer ...");
14
yield new SnookerPlayer();
15
}
16
17
default -> throw new IllegalArgumentException(
18
"Invalid player type: " + playerType);
19
};
20
}
В двух словах, стрелка не означает выражение вместо утверждения. Форма стрелки предотвращает падение .
Метки с двоеточием просто обозначают точку входа в исполнение. Оттуда это продолжается, даже когда он проходит другой ярлык. В
switch, мы знаем это как провал . Другими словами,caseметка определяет, куда переходит поток управления, но ему нужноbreak,yieldилиreturnчтобы прекратить поток черезswitch.С другой стороны, форма стрелки означает, что будет выполнен только блок справа. Это верно, без провала !
Готово! Полный пример доступен на GitHub .
Если вам понравилась эта статья, вам понравится моя книга « Проблемы кодирования Java» , полностью посвященная функциям JDK 8 — JDK 13.
Удачного кодирования!