programowanieProgramista Backend

Czym jest wyrażenie switch w Javie, jak różni się od klasycznego switch i jakie są niuanse jego użycia?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Historia pytania:

Przed Java 12 operator switch był używany wyłącznie jako instrukcja. Z wydaniem Java 12/14 pojawiły się wyrażenia switch (switch expression), które rozszerzyły składnię i możliwości operatora. Wyrażenia switch są przeznaczone do bardziej zwięzłego i wyrazistego kodu.

Problem:

Klasyczny switch często powoduje błędy: zapomniany break prowadzi do fall-through, trudności w czytelności przy wielu przypadkach, brak możliwości bezpośredniego zwrócenia wyniku w wyrażeniu, brak wyczerpującej kontroli wartości.

Rozwiązanie:

Wyrażenie switch może zwracać wartość, używać składni strzałkowej, wspierać wyczerpującą analizę na etapie kompilacji i obsługiwać null przez default. Ma składnię:

String result = switch(day) { case MONDAY, FRIDAY -> "Dzień roboczy"; case SATURDAY, SUNDAY -> "Weekend"; default -> throw new IllegalArgumentException(); };

Kluczowe cechy:

  • Switch stał się wyrażeniem: można przypisywać jego wynik do zmiennej.
  • Nowa składnia ułatwia czytanie i zapobiega zapomnianym breakom.
  • Wsparcie dla wielu etykiet (case A, B -> ...).

Pytania z podchwytliwością.

Czy switch może działać z enum, łańcuchami i null?

Z enum działa od Java 5. Z łańcuchami od Java 7. Null jest obsługiwany tylko przez default, w przeciwnym razie wystąpi NPE.

switch(day) { // day == null default: System.out.println("null"); } // działa

Co się stanie, jeśli nie zrealizujesz wszystkich wariantów enum w wyrażeniu switch?

Kompilator zażąda default lub implementacji dla wszystkich wartości. W przypadku ich braku wystąpi błąd kompilacji.

Czy można używać break w wyrażeniu switch nowego typu?

W wersji strzałkowej break nie jest potrzebny. Jeśli użyć bloku (case X -> { ... }), można zastosować yield do zwrócenia wartości:

int num = switch(x) { case 1 -> 10; case 2 -> { yield 20; } default -> 0; };

Typowe błędy i antywzorce

  • Brak default przy pracy z typami nie-nullowymi spowoduje błąd kompilacji.
  • Próba obsługi null poza default wywoła NullPointerException.
  • Używanie switch z dużą ilością zagnieżdżenia, zamiast polimorfizmu.

Przykład z życia

Negatywny przypadek

Klasyczny switch z int bez break:

switch(type) { case 1: actionA(); case 2: actionB(); // wywoływane zarówno przy type==1 jak i type==2 }

Plusy:

  • Szybko napisana.

Minusy:

  • Niedociągnięcia prowadzą do krytycznych błędów.
  • Kod jest trudny do odczytania i utrzymania.

Pozytywny przypadek

Użycie nowego wyrażenia switch do dopasowania enum do wyniku:

String status = switch(orderStatus) { case PAID -> "Opłacony"; case CANCELED -> "Anulowany"; default -> "W przetwarzaniu"; };

Plusy:

  • Wyczerpująca analiza — mniej błędów.
  • Kod jest zwarty i czytelny.

Minusy:

  • Wymaga Java 14+ i znajomości nowoczesnej składni.