JavaRush /Blog Java /Random-PL /Instrukcja Switch w Javie

Instrukcja Switch w Javie

Opublikowano w grupie Random-PL
Wyobraź sobie, że stoisz na rozwidleniu niczym bohater słynnego obrazu. Jeśli pójdziesz w lewo, stracisz konia; jeśli pójdziesz w prawo, zyskasz wiedzę. Jak zaprogramować taką sytuację? Pewnie już wiesz, że takiego wyboru dokonujemy za pomocą konstrukcji if-then i if-then-else .
if (turn_left) {
    System.out.println(«Коня потеряешь»);
}
if (turn_right) {
    System.out.println(“Знания обретёшь”);
}
else
    System.out.println(“Так и будешь стоять?);
A co jeśli takich utworów nie będzie dwóch, a 10? Czy istnieje ścieżka „w prawo”, „trochę w lewo”, „trochę bardziej w lewo” i tak dalej, w ilości 10 sztuk? Wyobraź sobie, jak w tej wersji rozrośnie się Twój kod if-then-else !
if (вариант1)
{}
else if (вариант2)
{}else if (вариантN).
Zatem nie masz jednego rozwidlenia warunków, ale kilka, powiedzmy 10 (ważne jest tutaj to, że liczba rozwidleń jest ograniczona). W takich sytuacjach istnieje specjalny operator selekcji - switch case Java .
switch (ВыражениеДляВыбора) {
           case  (Значение1):
               Код1;
               break;
           case (Значение2):
               Код2;
               break;
...
           case (ЗначениеN):
               КодN;
               break;
           default:
               КодВыбораПоУмолчанию;
               break;
       }
Kolejność wykonania w wyciągu jest następująca:
  • SelectionExpression jest oceniany. Następnie instrukcja switch porównuje wynikowe wyrażenie z następną wartością (w podanej kolejności).
  • Jeśli SelectExpression pasuje do wartości, wykonywany jest kod następujący po dwukropku.
  • Jeśli napotkana zostanie konstrukcja break , sterowanie zostanie przekazane poza poleceniem switch.
  • Jeśli nie zostaną znalezione żadne dopasowania pomiędzy ExpressionForSelection i Values, wówczas kontrola zostanie przekazana do DefaultSelectionCode.
Ważne punkty
  • Typ SelectionExpression instrukcji wyboru przełącznika w języku Java musi być jednym z następujących:

    • bajt , krótki , znak , int .
    • Ich opakowania to Byte , Short , Character , Integer .
    • String (od Java 7).
    • Wyliczenie ( Enum ).
  • Domyślny blok jest opcjonalny, wówczas jeśli SelectionExpression i Values ​​nie będą zgodne, żadna akcja nie zostanie wykonana.
  • break jest opcjonalny; jeśli go nie ma, kod będzie kontynuował wykonywanie (ignorując dalsze porównania wartości w blokach case) aż do breaknapotkania pierwszej instrukcji switch lub do końca.
  • jeśli konieczne jest wykonanie tego samego kodu dla kilku opcji wyboru, aby uniknąć powielania, wskazujemy przed nim kilka odpowiednich wartości w kolejnych blokach przypadków .

Przejdźmy do praktyki stosowania instrukcji switch w Javie

Nie martwcie się, teorię mamy już za sobą, a po kolejnych przykładach wszystko stanie się znacznie jaśniejsze. Więc zacznijmy. Spójrzmy na przykład z astronomii dotyczący planet Układu Słonecznego. Zgodnie z najnowszymi przepisami międzynarodowymi wykluczymy Plutona (ze względu na właściwości jego orbity). Pamiętajmy, że nasze planety znajdują się od Słońca w następującej kolejności: Merkury, Wenus, Ziemia, Mars, Jowisz, Saturn, Uran i Neptun. Stwórzmy metodę Java, która na wejściu otrzyma numer seryjny planety (w odniesieniu do odległości od Słońca), a na wyjściu wyświetli główny skład atmosfery tej planety w postaci Listy <String> . Przypomnę, że niektóre planety mają podobny skład atmosfery. Zatem Wenus i Mars zawierają głównie dwutlenek węgla, Jowisz i Saturn składają się z wodoru i helu, a Uran i Neptun, oprócz ostatniej pary gazów, mają także metan. Nasza funkcja:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add(„Brak atmosfery”);
            break;
        case 2:
        case 4: result.add("Dwutlenek węgla");
            break;
        case 3: result.add("Dwutlenek węgla");
            result.add("Azot");
            result.add("Tlen");
            break;
        case 5:
        case 6: result.add("Wodór");
            result.add("Hel");
            break;
        case 7:
        case 8: result.add("Metan");
            result.add("Wodór");
            result.add("Hel");
            break;
        default:
            break;
    }
    return result;
}
Uwaga: porównaliśmy ten sam kod z planetami o identycznym składzie atmosfery. Zrobiliśmy to za pomocą kolejnych konstrukcji przypadków . Jeśli więc chcemy poznać skład atmosfery naszej macierzystej planety, wywołujemy naszą metodę z parametrem 3:
getPlanetAtmosphere(3).
System.out.println(getPlanetAtmosphere(3)) вернет нам [Углекислый газ, Азот, Кислород].
Eksperymentuj z break Co się stanie, jeśli usuniemy wszystkie instrukcje break ? Spróbujmy tego w praktyce:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add(„Brak atmosfery”);
        case 2:
        case 4: result.add("Dwutlenek węgla");
        case 3: result.add("Dwutlenek węgla");
            result.add("Azot");
            result.add("Tlen");
        case 5:
        case 6: result.add("Wodór");
            result.add("Hel");
        case 7:
        case 8: result.add("Metan");
            result.add("Wodór");
            result.add("Hel");
        default:
    }
    return result;
}
Jeśli wydrukujemy wynik metody System.out.println(getPlanetAtmosphere(3)), to nasza rodzima planeta nie będzie już tak odpowiednia do życia. Lub odpowiedni? Oceńcie sami: [Dwutlenek węgla, azot, tlen, wodór, hel, metan, wodór, hel], dlaczego tak się stało? Program wykonywał wszystkie przypadki po pierwszym dopasowaniu i do końca bloku przełączającego.

Nadmierna przerwa na optymalizację

Należy zauważyć, że możemy ulepszyć tę metodę, zmieniając układ dyrektyw przerwania i opcji wyboru
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add(„Brak atmosfery”);
                break;
        case 3: result.add("Azot");
                result.add("Tlen");
        case 2:
        case 4: result.add("Dwutlenek węgla");
                break;
        case 7:
        case 8: result.add("Metan");
        case 5:
        case 6: result.add("Wodór");
                result.add("Hel");
    }
     return result;
}
Wygląda na krótszą, prawda? Zmniejszyliśmy całkowitą liczbę instrukcji, bawiąc się kolejnością przypadków i przegrupowując. Teraz każdy rodzaj gazu dodawany jest do listy tylko w jednej linijce kodu. Lista ostatniego przykładu metody jest pokazana jedynie w celu zademonstrowania pracy; zdecydowanie nie zaleca się pisania w takim stylu. Jeśli autor (a tym bardziej zewnętrzni programiści) podobnego kodu będzie musiał go utrzymywać, bardzo trudno będzie przywrócić logikę tworzenia bloków wyboru i kodu wykonywalnego dla instrukcji Java Switch.

Różnice od jeśli

Chociaż instrukcje if i switch mają podobny wygląd , nie zapominaj, że operator wielokrotnego wyboru switch opiera wybór opcji wykonania na KONKRETNEJ WARTOŚCI, natomiast in if. może być dowolnym wyrażeniem logicznym. Weź ten fakt pod uwagę projektując swój kod. Przyjrzyjmy się bliżej innowacjom przełącznika w różnych wersjach Javy.

Przełącz w Javie 7

Przed wersją Java 7 jako wartości przełącznika można było używać operacji podstawowych typu byte, short, char i int. Obsługiwane było również wyliczenie i opakowania typów pierwotnych wymienionych powyżej: Character, Byte, Short i Integer. Ale często musimy znaleźć wartość ciągu przełącznika Java! Tak by to wyglądało w Javie 6:
DayOfWeek day = DayOfWeek.fromValue("Thursday");

switch (day) {
  case MONDAY:
     System.out.println("Today is windy !");
     break;
  case THURSDAY:
     System.out.println("Today is sunny !");
     break;
  case WEDNESDAY:
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
I wyliczenie:
public enum DayOfWeek {
  MONDAY("Monday"),
  THURSDAY("Thursday"),
  WEDNESDAY("Wednesday"),
  NOT_FOUND("Not found");

  private final String value;

  DayOfWeek(final String value) {
     this.value = value;
  }

  public static DayOfWeek fromValue(String value) {
     for (final DayOfWeek dayOfWeek : values()) {
        if (dayOfWeek.value.equalsIgnoreCase(value)) {
           return dayOfWeek;
        }
     }
     return NOT_FOUND;
  }
}
Ale począwszy od Java 7 możliwe było użycie typu String jako wartości przełącznika:
String day = "Thursday";

switch (day) {
  case "Monday":
     System.out.println("Today is windy !");
     break;
  case "Thursday":
     System.out.println("Today is sunny !");
     break;
  case "Wednesday":
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
}
Pomimo nowych funkcji podejście wykorzystujące wyliczenie jest bardziej elastyczne i zalecane do użycia: możemy ponownie wykorzystać to wyliczenie wiele razy.

Przełącz w Javie 12

W Javie 12 udoskonalono wyrażenia Switch do dopasowywania wzorców. Jeśli użyjemy Switcha jak w powyższym przykładzie, aby ustawić wartość jakiejś zmiennej, musieliśmy obliczyć wartość i przypisać ją do danej zmiennej, a następnie zastosować break:
int count = 2;
int value;
switch (count) {
  case 1:
     value = 12;
     break;
  case 2:
     value = 32;
     break;
  case 3:
     value = 52;
     break;
  default:
     value = 0;
}
Ale dzięki możliwościom Java 12 możemy przepisać to wyrażenie w następujący sposób:
int value = switch (count) {
  case 1:
     break 12;
  case 2:
     break 32;
  case 3:
     break 52;
  default:
     break 0;
};
Omówmy trochę zmiany:
  1. Jeśli wcześniej ustawialiśmy wartość zmiennej wewnątrz bloków case, gdyż sama instrukcja switch nie mogła nic zwrócić, teraz mamy taką możliwość i bezpośrednio zwracamy wartość za pomocą switch.

  2. Wcześniej nie mogliśmy już mieć niczego po prawej stronie break, ale teraz używamy tego jako instrukcji return, aby zwrócić wartość naszego przełącznika. Dwukropki oznaczają punkt wejścia do bloku instrukcji. Oznacza to, że od tego momentu rozpoczyna się wykonywanie całego poniższego kodu, nawet jeśli napotkana zostanie inna etykieta.

    Rezultatem jest kompleksowe przejście od znaku do znaku, zwane także opadaniem .

Instrukcja Switch w Javie — 2Aby ukończyć takie przejście, musisz albo całkowicie przejść przez wszystkie elementy, albo skorzystać z przerwy lub powrotu. Innowacja w Javie 12 daje nam możliwość użycia operatora lambda, co z kolei gwarantuje, że zostanie wykonany tylko kod po jego prawej stronie. Bez żadnych „porażek”. Jak będzie wyglądał poprzedni przykład w tym przypadku:
int count = 2;
int value = switch (count) {
  case 1 -> 12;
  case 2 -> 32;
  case 3 -> 52;
  default -> 0;
};
Kod stał się znacznie prostszy, prawda? I jeszcze jedno: operator lambda może również służyć jako typowy analog dwukropka, po którym następuje cały blok z niektórymi operacjami:
int count = 2;
int value = switch (count) {
  case 1 -> {
     //niektóre operacje obliczeniowe...
     break 12;
  }
  case 2 -> {
     //niektóre operacje obliczeniowe...
     break 32;
  }
  case 3 -> {
     //niektóre operacje obliczeniowe...
     break 52;
  }
  default -> {
     //niektóre operacje obliczeniowe...
     break 0;
  }
};
A co, jeśli w niektórych przypadkach wartość zwracana jest taka sama? Okazuje się, że tak naprawdę mamy te same przypadki dla różnych wartości. Oto, jak można to skrócić, korzystając z nowych funkcji w Javie 12:
int count = 2;
int value = switch (count) {
  case 1, 3, 5 -> 12;
  case 2, 4, 6 -> 52;
  default -> 0;
};

Przełącz w Javie 13

W Javie 13 zmienił się sposób, w jaki przełącznik zwraca wartość. Jeśli w Javie 12 napisaliśmy wartość zwracaną po break, która służyła nam jako zwrot dla bloku switch, teraz zwrócimy tę wartość za pomocą słowa Yield . Spójrzmy:
int value = switch (count) {
  case 1:
     yield 12;
  case 2:
     yield 32;
  case 3:
     yield 52;
  default:
     yield 0;
};
Jednocześnie kod napisany w Javie 12 przy użyciu break to return nie zostanie skompilowany (( Instrukcja Switch w Javie — 3Break zostanie użyty, ale w sytuacjach, gdy nie musimy niczego zwracać.

Całkowity

  • Użyj instrukcji case , gdy istnieją więcej niż dwie gałęzie, aby uniknąć zaśmiecania kodu strukturami if.
  • Nie zapomnij zakończyć bloku logicznego każdej gałęzi odpowiadającej określonej wartości (blok przypadków) wywołaniem przerwania .
  • Oprócz niektórych typów pierwotnych instrukcja switch może również używać typów Enum i String jako wyrażeń .
  • Zapamiętaj domyślny blok - użyj go do obsługi niezaplanowanych wartości selekcji.
  • Aby zoptymalizować wydajność, przenieś gałęzie kodu z najczęściej wybieranymi opcjami na początek bloku przełączników.
  • Nie dajcie się zwieść „optymalizacji” usuwając przerwę na końcu bloku wyboru przypadków – taki kod jest trudny do zrozumienia, a co za tym idzie – trudny do utrzymania w trakcie jego tworzenia.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION