Напевно, тобі доводилося використовувати в коді з великою кількістю умов або 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, а 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 і не був повноцінною частиною версії мови.