1. Co nowego w switch
Jeśli zdarzało ci się pisać w Javie przed wersją 14, to switch wyglądał mniej więcej tak:
switch (day)
{
case MONDAY:
System.out.println("Początek tygodnia!");
break;
case FRIDAY:
System.out.println("Piątek, hura!");
break;
default:
System.out.println("Zwykły dzień.");
break;
}
Niby nic strasznego, ale:
- Trzeba pamiętać o break (w przeciwnym razie „przejdziemy” do następnego case).
- Dużo powtarzającego się kodu.
- Jeśli chcesz zwrócić wartość, musisz wcześniej zadeklarować zmienną i przypisywać do niej wartość w każdym case.
Java 14+ powiedziała: dość tego! Czas uczynić switch wygodniejszym i nowocześniejszym.
Główne nowości:
- Switch stał się wyrażeniem, a nie tylko instrukcją — teraz może zwracać wartość.
- Nowa składnia ze strzałką -> zamiast dwukropków i break.
- Kilka case po przecinku — dla tej samej logiki.
- Kompilator sprawdza, czy wszystkie warianty są obsłużone (zwłaszcza przy enum).
- Brak ryzyka przechodzenia dalej (fall-through) — teraz jest to możliwe tylko jawnie.
2. Składnia wyrażenia switch
switch (value)
{
case A, B -> result1;
case C -> {
// kilka działań
yield result2;
}
default -> defaultResult;
}
-> i
yield
Podstawowy przykład
Przejdźmy od razu do rzeczy. Tak można teraz zwracać wartość z switch:
DayOfWeek day = DayOfWeek.MONDAY;
String message = switch (day)
{
case MONDAY, FRIDAY, SUNDAY -> "Krótki tydzień lub dzień wolny!";
case TUESDAY -> "Wtorek — ciężki dzień.";
case WEDNESDAY, THURSDAY -> "Środek tygodnia!";
case SATURDAY -> "Hurra, sobota!";
// Obowiązkowo musi być default, jeśli nie wszystkie warianty są obsłużone
default -> "Jakiś dziwny dzień...";
};
System.out.println(message);
Co się tu dzieje:
- switch (day) — wyrażenie zwracające wartość.
- Po strzałce -> podajesz wynik dla danego case.
- Kilka case można połączyć przecinkiem.
- Nie ma ani jednego break — Java sama wie, gdzie kończy się gałąź.
- Można od razu przypisać wynik do zmiennej message.
Przykład z liczbami
int code = 404;
String result = switch (code)
{
case 200 -> "OK";
case 400, 404 -> "Błąd klienta";
case 500 -> "Błąd serwera";
default -> "Nieznany kod";
};
System.out.println(result);
Przykład z napisami
String command = "start";
String status = switch (command)
{
case "start" -> "Start!";
case "stop" -> "Zatrzymanie!";
case "pause" -> "Pauza...";
default -> "Nieznane polecenie";
};
System.out.println(status);
Użycie bloku z yield
Czasem chcesz wykonać kilka czynności dla jednego case (np. obliczyć coś złożonego albo zalogować zdarzenie). Do tego można użyć bloku { ... } i słowa kluczowego yield:
int n = 7;
String parity = switch (n % 2)
{
case 0 -> "Parzysta";
case 1 ->
{
System.out.println("Wykryto liczbę nieparzystą: " + n);
yield "Nieparzysta";
}
default -> "Coś dziwnego";
};
System.out.println(parity);
Ważne: w bloku musi być yield, który zwraca wartość dla tego case.
3. Zalety nowej składni
Brak potrzeby używania break
W klasycznym switch zapomniane break to źródło bólu i zagadkowych błędów. W nowej składni break nie jest w ogóle potrzebne: każda gałąź kończy się automatycznie.
Kompilator sprawdza obsługę wszystkich wariantów
Jeśli używasz enum i nie obsłużyłeś wszystkich wartości — kompilator nie pozwoli zbudować projektu bez default. To czyni kod bardziej niezawodnym.
Brak „przechodzenia dalej” (fall-through)
W klasycznym switch, jeśli zapomnisz break, wykonanie „przejdzie” do następnego case. W nowej składni to niemożliwe (chyba że użyjesz bloku z instrukcjami i jawnie napiszesz break — ale tutaj nie jest potrzebny).
Kod bardziej zwięzły i czytelny
Porównajmy:
Przed:
String result;
switch (status) {
case "OK":
result = "Wszystko w porządku";
break;
case "ERROR":
result = "Błąd";
break;
default:
result = "Nieznane";
break;
}
Po:
String result = switch (status) {
case "OK" -> "Wszystko w porządku";
case "ERROR" -> "Błąd";
default -> "Nieznane";
};
Kilka case — jedna logika
case MONDAY, FRIDAY, SUNDAY -> "Dzień wolny lub krótki dzień!";
4. Porównanie z klasycznym switch
| Cecha | Klasyczny switch | Nowy switch |
|---|---|---|
| break jest obowiązkowy | Tak | Nie |
| Przechodzenie dalej (fall-through) | Tak | Nie |
| Może zwracać wartość | Nie (tylko przez zmienną) | Tak (wyrażenie) |
| Kilka case po przecinku | Nie | Tak |
| Weryfikacja wszystkich wariantów | Nie | Tak (zwłaszcza z enum) |
| Zwięzłość | Dużo kodu | Krótko i jasno |
| Użycie z enum i String | Tak | Tak |
5. Zgodność z enum i String
Przykład z enum
Załóżmy, że mamy wyliczenie:
enum DayOfWeek
{
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Użyjemy go w nowym switch:
DayOfWeek today = DayOfWeek.WEDNESDAY;
String mood = switch (today)
{
case MONDAY -> "Ciężko wstać...";
case FRIDAY -> "Weekend już blisko!";
case SATURDAY, SUNDAY -> "Hurra, odpoczynek!";
default -> "Dzień roboczy.";
};
System.out.println(mood);
Przykład ze String
String season = "summer";
String activity = switch (season)
{
case "winter" -> "Jeździć na łyżwach";
case "summer" -> "Pływać w jeziorze";
case "autumn" -> "Zbierać grzyby";
case "spring" -> "Słuchać śpiewu ptaków";
default -> "Nieznana pora roku";
};
System.out.println(activity);
6. Przepisujemy stary switch na nowy styl
Było:
int day = 3;
String dayName;
switch (day)
{
case 1:
dayName = "Poniedziałek";
break;
case 2:
dayName = "Wtorek";
break;
case 3:
dayName = "Środa";
break;
default:
dayName = "Nieznany dzień";
break;
}
System.out.println(dayName);
Jest:
int day = 3;
String dayName = switch (day)
{
case 1 -> "Poniedziałek";
case 2 -> "Wtorek";
case 3 -> "Środa";
default -> "Nieznany dzień";
};
System.out.println(dayName);
Jeszcze jeden przykład: wiele case — jedna logika
int score = 5;
String grade = switch (score)
{
case 5, 6, 7 -> "Dobrze";
case 8, 9, 10 -> "Świetnie";
default -> "Trzeba się postarać";
};
System.out.println(grade);
7. Typowe błędy i uwagi
Błąd nr 1: brak default, jeśli nie wszystkie warianty są obsłużone. Jeśli używasz wyrażenia switch z typem, który może przyjmować wartości spoza wymienionych w case (np. z int lub String), kompilator zażąda default. Dla enum, jeśli nie obsłużysz wszystkich wartości, default też jest obowiązkowy.
Błąd nr 2: zapomniany yield w bloku. Jeśli używasz nawiasów klamrowych dla case (trzeba wykonać kilka czynności), nie zapomnij o yield — bez niego kompilator zgłosi błąd: "Missing yield statement".
Błąd nr 3: niezgodność typów. Wszystkie gałęzie wyrażenia switch muszą zwracać wartości tego samego typu; w przeciwnym razie kompilator nie przepuści kodu.
Błąd nr 4: zduplikowane wartości case. Nie można podać tego samego case dwa razy — kompilator od razu zgłosi błąd.
GO TO FULL VERSION