Наверняка тебе доводилось использовать в коде с большим количеством условий либо if-else, или switch. Но у этой альтернативы есть недостатки в использовании: в народе switch даже прозвали “антипаттерном”.

Что это такое? Антипаттерн — это шаблон плохого кода, плохого решения проблемы. В программировании стараются избегать использование их в коде, так как они ухудшают качество кода.

Но есть и хорошая новость: с выходом новых версий Java многое изменилось в систаксисе языка, и одно из изменений затронуло как раз switch. Интересно? Тогда пойдем разбираться.

Для начала стоит уточнить, почему switch — это антипаттерн. Рассмотрим следующий код:


switch (condition) {
    case "DECEMBER":
        seasonNumber = 1;
        break;
    case "JANUARY":
        seasonNumber = 1;
        break;
    case "FEBRUARY":
        seasonNumber = 1;
        break;
    default:
        seasonNumber = 0;
}

Пока что не совсем понятно, почему это "антипаттерн", это правда.

Но что, если мы добавим еще case блоков, и код будет выглядеть вот так:


switch (condition) {
    case "DECEMBER":
        seasonNumber = 1;
        break;
    case "JANUARY":
        seasonNumber = 1;
        break;
    case "FEBRUARY":
        seasonNumber = 1;
        break;
    case “MARCH”:
        seasonNumber = 2;
        break;
    case “APRIL”:
        seasonNumber = 2;
        break;
    case “MAY”:
        seasonNumber = 2;
        break;
    default:
        seasonNumber = 0;
}

Добавим еще несколько строк, и код станет длиннее. А потом можно добавить еще и еще строк, и никто нам не помешает это сделать.

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

Разница между switch statement и switch expression

В Java 14 вышел новый switch, улучшенный. Теперь это уже не switch statement, a switch expression.

Ты спросишь, в чем разница? В том, что statement – это инструкция в коде, которая делает определенный набор операций, а expression – это фрагмент кода который делает некоторое исчисление и возвращает результат.

То есть теперь результат работы switch ты можешь сохранить в переменную.

Давай наконец посмотрим, как выглядит новый switch:


var result = switch(month) {
     case DECEMBER, JANUARY, FEBRUARY -> 1;
     case MARCH, APRIL, MAY -> 2;
    case JUNE, JULY, AUGUST -> 3;
    case SEPTEMBER, OCTOBER, NOVEMBER -> 4;
    default -> 0; 
};

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

Оператор ->

Также стоит обратить внимание на оператор -> — arrow operator. Он может быть тебе знаком, если у тебя есть опыт в использовании Лямбда-выражений.

То есть теперь ты можешь писать switch в стиле Лямбда, и это выглядит круто. Использование стрелки (arrow оператора) говорит о том, что теперь компилятор не будет идти к следующему case выражению (если у нас нет break или return в этом case блоке), а вернет тебе значение, которое будет справа от стрелки.

Ты также можешь написать код, который не будет являться выражением и ничего не будет возвращать, а просто выполнять определенные действия:


switch(condition) {
    case TRUE, FALSE -> System.out.println("True/false");
  
    default -> System.out.println("Another");
}

Обрати внимание, что теперь switch без оператора break. Его убрали в Java 13 и заменили словом yield.

Что такое yield и где его можно использовать

Когда switch состоит из одной строчки, arrow -> сам вернет это значение. Но что делать, если у нас не одна, а несколько строк кода? Arrow в таких случаях не вернет значения, так как строк не одна, а несколько.

Может, использовать return? Он служит в Java для того, чтобы возвращать значения. Но увы, нет: return со свитчем не работает. Так что же использовать? Раньше был break, но в Java 13 его убрали. Зато появилось yield — новое ключевое слово, которое поможет тебе вернуть значение со свитча, аналог return в методах.


var result = switch(condition) {
//…
case "Hi" -> "greeting"
//…
};  

Этот код содержит одну строку, и -> оператор сам вернет тебе значение “greeting”.

Но в случаях, когда у нас блок кода:


var result = switch(condition) {
//…
case "Hi" -> {
// Твой код
 Здесь нужно вернуть "greeting"
	}
};  

Тебе поможет вернуть значение именно yield:


var result = switch(condition) {
//…
case "Hi" -> {
// Твой код
 yield "greeting";

	}
};

yield добавлен в Java 13 для случаев, когда в case блоке у нас больше одной строки кода, и нужно вернуть результат.

Тебе наверняка уже хочется попробовать на практике новый switch, но помни, что для этого тебе нужна Java 14+ версии. С более ранними версиями switch будет доступен только при указании флага “--enable-preview” при запуске, так как до версии 14 он был в режиме preview и не являлся полноценной частью версии языка.

На этом все, увидимся!