Это супер-быстрый гид по 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.
Удачного кодирования!