Вирази switch в Java 14 та пізніших версіях

pic

Фото від Museums Victoria на Unsplash

Хоча це, можливо, не так травматично, як виключення через null pointer, але проблема fall-through в Switch-Case завдала чимало головного болю багатьом програмістам на Java. Хоча в деяких випадках fall-through може бути зручним, найчастіше це призводить до несподіваних проблем.

Як приклад, розглянемо маленьку програму, яка повинна вивести сьогоднішню дату і кількість днів у поточному місяці.

LocalDate today = LocalDate.now();  
 System.out.println("Today is " + today.toString());  
 Month month = today.getMonth();  
 int numberOfDays = 0;  
 switch (month) {  
 case JANUARY:  
 case MARCH:  
 case MAY:  
 case JULY:  
 case AUGUST:  
 case OCTOBER:  
 case DECEMBER:  
 numberOfDays = 31;  
 case FEBRUARY:  
 if (today.isLeapYear()) {  
 numberOfDays = 29;  
 } else {  
 numberOfDays = 28;  
 }  
 case APRIL:  
 case JUNE:  
 case SEPTEMBER:  
 case NOVEMBER:  
 numberOfDays = 30;  
 }  
 System.out.println("The month "   
 + month.getDisplayName(TextStyle.FULL,   
 Locale.US) + " has "   
 + numberOfDays + " days");

Виведення буде помилковим більше половини року.

Today is 2025–01–03
The month January has 30 days

Зрозуміло, що це неправильно. Січень має 31 день, як і сказано в Old Farmer’s Almanac. Це не велика проблема в тестовому прикладі. Однак не важко уявити, як fall-through в Switch-Case може спричинити проблеми в реальних програмах.

Ваше середовище розробки (IDE), наприклад Apache NetBeans, ймовірно попереджає вас про не використані присвоєння.

pic

Якщо ми просто додамо Break після рядків з попередженнями, NetBeans усуне ці попередження, і наша програма повинна вивести правильний результат.

Today is 2025–01–03
The month January has 31 days

Але якщо ваша IDE використовує Java 12 або 13 з увімкненими попередніми функціями, або Java 14 або пізніші версії, то ви можете отримати попередження на рядку з “switch (month)”. У NetBeans це попередження вказує на можливість використати "rule switch". Інші IDE можуть сказати, що ви можете використати "switch expression".

Switch expression були додані як попередня функція в Java 12, залишалися в попередньому режимі в Java 13 і були офіційно прийняті в Java 14.

NetBeans переписав Switch-Case вище, як показано нижче:

switch (month) {  
 case JANUARY, MARCH, MAY, JULY, AUGUST, OCTOBER,   
 DECEMBER -> numberOfDays = 31;  
 case FEBRUARY -> {  
 if (today.isLeapYear()) {  
 numberOfDays = 29;  
 } else {  
 numberOfDays = 28;  
 }  
 }  
 case APRIL, JUNE, SEPTEMBER, NOVEMBER ->   
 numberOfDays = 30;  
 }

Але ми можемо зробити краще. Ми можемо написати щось, що майже нагадує Match-Case в Scala.

int numberOfDays = switch (month) {  
 case JANUARY, MARCH, MAY, JULY, AUGUST, OCTOBER,   
 DECEMBER -> 31;  
 case FEBRUARY -> {  
 if (today.isLeapYear()) {  
 yield 29;  
 } else {  
 yield 28;  
 }  
 }  
 case APRIL, JUNE, SEPTEMBER, NOVEMBER -> 30;  
 };

Зверніть увагу на використання фігурних дужок і зарезервоване слово yield в випадку лютого.

Switch expression повинні бути вичерпними. Якби ми використовували 32-бітні цілі числа замість типу enum Month, нам довелося б надати випадок Default (використання типу enum також позбавляє нас турбот про те, чи є січень 0 чи 1).

Багато хто з вас, хто читає це, ймовірно, все ще використовує Java 8 у своїй професійній роботі через вимоги клієнтів. Але для ваших особистих проєктів, можливо, варто оновитися до новішої версії Java і скористатися можливостями, як от Switch expression.

Перекладено з: Switch expressions in Java 14 and later

Leave a Reply

Your email address will not be published. Required fields are marked *