1. Wprowadzenie
Wyobraź sobie: piszesz program dla kawiarni. Użytkownik może wybrać napój, a Ty musisz na ten wybór zareagować. Oczywiście można użyć mnóstwa if-else if-else, ale nie wygląda to najlepiej:
if (choice == 1)
{
System.out.println("Wybrano espresso.");
}
else if (choice == 2)
{
System.out.println("Wybrano cappuccino.");
}
else if (choice == 3)
{
System.out.println("Wybrano latte.");
}
else
{
System.out.println("Nie ma takiego napoju.");
}
Przyznasz, wygląda to ociężale. A jeśli wariantów będzie 10 lub 20? Właśnie tu z pomocą przychodzi operator switch, który pozwala elegancko i zwięźle zrealizować wybór spośród wielu opcji na podstawie wartości zmiennej.
Składnia klasycznego switch
Składnia switch w Javie wygląda tak:
switch (wyrażenie)
{
case wartość1:
// akcje, jeśli wyrażenie == wartość1
break;
case wartość2:
// akcje, jeśli wyrażenie == wartość2
break;
...
default:
// akcje, jeśli nie pasuje do żadnego case
break;
}
switch w Javie
Kluczowe elementy:
- switch (wyrażenie) — wyrażenie, którego wynik jest porównywany z każdym case.
- case wartość: — wariant, z którym porównuje się wyrażenie.
- break; — kończy wykonanie bloku switch (w przeciwnym razie — „fall-through” do następnego case).
- default: — wykonywany, jeśli nie pasuje do żadnego case.
2. Przykłady użycia switch
Przykład 1: Klasyka gatunku — wybór napoju
Zaimplementujmy menu dla kawiarni:
import java.util.Scanner;
public class CoffeeShop
{
public static void main(String[] args)
{
Scanner console = new Scanner(System.in);
System.out.println("Wybierz napój:");
System.out.println("1 - Espresso");
System.out.println("2 - Cappuccino");
System.out.println("3 - Latte");
int choice = console.nextInt();
switch (choice)
{
case 1:
System.out.println("Wybrano espresso.");
break;
case 2:
System.out.println("Wybrano cappuccino.");
break;
case 3:
System.out.println("Wybrano latte.");
break;
default:
System.out.println("Nie ma takiego napoju.");
break;
}
}
}
Co się dzieje:
- Użytkownik podaje numer napoju.
- Wartość zmiennej choice jest porównywana z każdym case.
- Jeśli się zgadza — wykonywany jest odpowiedni blok, następnie break kończy wykonanie switch.
- Jeśli nic nie pasuje — wykonywany jest default.
Przykład 2: Przełączanie po napisach
Niewiele typów można używać wewnątrz switch, ale napisy — można! To wygodne dla menu poleceń:
import java.util.Scanner;
public class CommandMenu
{
public static void main(String[] args)
{
Scanner console = new Scanner(System.in);
System.out.println("Wpisz polecenie (start, stop, pause):");
String command = console.nextLine();
switch (command)
{
case "start":
System.out.println("Uruchomienie programu!");
break;
case "stop":
System.out.println("Zatrzymanie programu.");
break;
case "pause":
System.out.println("Pauza.");
break;
default:
System.out.println("Nieznane polecenie.");
break;
}
}
}
Zwróć uwagę: porównywanie napisów w switch jest czułe na wielkość liter! "Start" i "start" to różne napisy.
3. Jakie typy obsługuje klasyczny switch?
W klasycznym switch można używać tylko określonych typów:
- Prymitywne typy całkowite: byte, short, char, int
- Wyliczenia: enum (omówimy je na następnej lekcji)
- Napisy: String — porównywane z uwzględnieniem wielkości liter
Nie można używać: boolean, float, double, tablic, dowolnych obiektów klas (poza enum i String).
Przykład z char
char grade = 'B';
switch (grade)
{
case 'A':
System.out.println("Świetnie!");
break;
case 'B':
System.out.println("Dobrze.");
break;
case 'C':
System.out.println("Zadowalająco.");
break;
default:
System.out.println("Spróbuj ponownie.");
break;
}
4. Obowiązkowy break: co się stanie, jeśli o nim zapomnisz?
Najczęstszy błąd początkujących — zapomnieć o break;. Zobaczmy, co się stanie:
int day = 2;
switch (day)
{
case 1:
System.out.println("Poniedziałek");
break;
case 2:
System.out.println("Wtorek");
case 3:
System.out.println("Środa");
break;
default:
System.out.println("Nieznany dzień");
break;
}
Wynik:
Wtorek
Środa
Dlaczego? Bo po case 2 nie ma break, więc wykonanie „wpada” do następnego case (to się nazywa fall-through). Czasem jest to przydatne, ale najczęściej — błąd.
5. Grupowanie case: gdy kilka wariantów zachowuje się tak samo
Jeśli dla kilku wartości potrzebne jest to samo zachowanie, można wypisać je jedna po drugiej:
int month = 1;
switch (month)
{
case 12:
case 1:
case 2:
System.out.println("Zima");
break;
case 3:
case 4:
case 5:
System.out.println("Wiosna");
break;
case 6:
case 7:
case 8:
System.out.println("Lato");
break;
case 9:
case 10:
case 11:
System.out.println("Jesień");
break;
default:
System.out.println("Nieznany miesiąc");
break;
}
Tutaj: jeśli month — 12, 1 lub 2, program wypisze "Zima".
6. Porównanie: switch i if-else
| Scenariusz | if-else | switch |
|---|---|---|
| Wiele wariantów | Długi łańcuch, gorsza czytelność | Krótko, wszystkie warianty widać od razu |
| Porównywanie zakresów | Można użyć (if (x > 5 && x < 10)) | Nie można, tylko konkretne wartości |
| Obsługiwane typy | Dowolne | Tylko określone (patrz wyżej) |
| Pułapka z break | Nie | Tak, trzeba pilnować break |
7. Typowe błędy przy pracy ze switch
Błąd nr 1: zapomniany break
Najczęstsza przyczyna błędów: zapomniano o break — i kod wykonuje nie ten case, którego oczekiwano.
Błąd nr 2: nieobsługiwany typ
Próbujesz użyć double, float lub boolean — kompilator powie „nie można”.
Błąd nr 3: napisy o różnej wielkości liter
Użytkownik wpisał "Start", a Ty oczekujesz "start" — switch nie zadziała. Lepiej wcześniej sprowadzić napisy do jednej wielkości liter:
switch (command.toLowerCase())
{
case "start":
// ...
}
Błąd nr 4: zmienna w case, a nie stała
W case dozwolone są tylko stałe. Jeśli użyjesz zmiennej — będzie błąd kompilacji.
Błąd nr 5: duplikujące się case
Dwie takie same wartości case — kompilator tego nie wybaczy.
GO TO FULL VERSION