Deklaracje zamiany z String
przypadkami zostały zaimplementowane w Javie SE 7 , co najmniej 16 lat po ich pierwszym zgłoszeniu. Nie podano wyraźnego powodu opóźnienia, ale prawdopodobnie miało to związek z wydajnością.
Wdrożenie w JDK 7
Funkcja została teraz zaimplementowana w javac
procesie „usuwania cukru”; czysta, wysokopoziomowa składnia wykorzystująca String
stałe w case
deklaracjach jest rozszerzana w czasie kompilacji do bardziej złożonego kodu zgodnie ze wzorcem. Wynikowy kod używa instrukcji JVM, które zawsze istniały.
A switch
z String
przypadkami jest tłumaczone na dwa przełączniki podczas kompilacji. Pierwszy mapuje każdy ciąg na unikalną liczbę całkowitą - jego pozycję w oryginalnym przełączniku. Odbywa się to poprzez pierwsze włączenie kodu skrótu etykiety. Odpowiednim przypadkiem jest if
instrukcja, która testuje równość łańcucha; jeśli w haszu występują kolizje, test jest kaskadowy if-else-if
. Drugi przełącznik odzwierciedla to w oryginalnym kodzie źródłowym, ale zastępuje etykiety liter odpowiednimi pozycjami. Ten dwuetapowy proces ułatwia zachowanie kontroli przepływu oryginalnego przełącznika.
Przełączniki w JVM
Aby uzyskać więcej szczegółów technicznych switch
, można zapoznać się ze specyfikacją JVM, w której opisano kompilację instrukcji switch . Krótko mówiąc, istnieją dwie różne instrukcje JVM, których można użyć dla przełącznika, w zależności od rzadkości stałych używanych przez przypadki. Oba zależą od wykorzystania stałych liczb całkowitych dla każdego przypadku, aby wykonać je skutecznie.
Jeśli stałe są gęste, są one używane jako indeks (po odjęciu najniższej wartości) do tabeli wskaźników instrukcji - tableswitch
instrukcji.
Jeśli stałe są rzadkie, przeprowadzane jest binarne wyszukiwanie poprawnej wielkości liter - lookupswitch
instrukcja.
W odcukrzania switch
na String
obiektach, obie instrukcje mogą być użyte. lookupswitch
Nadaje pierwszy przełącznik na kody hash znaleźć oryginalne stanowisko w sprawie. Wynikowy porządek jest naturalnym dopasowaniem do tableswitch
.
Obie instrukcje wymagają sortowania stałych liczb całkowitych przypisanych do każdego przypadku w czasie kompilacji. W czasie wykonywania O(1)
wydajność na tableswitch
ogół wydaje się lepsza niż O(log(n))
wydajność lookupswitch
, ale wymaga pewnej analizy w celu ustalenia, czy tabela jest wystarczająco gęsta, aby uzasadnić kompromis czasoprzestrzenny. Bill Venners napisał świetny artykuł, który omawia to bardziej szczegółowo, wraz z ukrytym spojrzeniem na inne instrukcje kontroli przepływu Java.
Przed JDK 7
Przed JDK 7 enum
mógł w przybliżeniu String
przełącznik oparty na przełączniku. Wykorzystuje statycznąvalueOf
metodę generowaną przez kompilator dla każdego enum
typu. Na przykład:
Pill p = Pill.valueOf(str);
switch(p) {
case RED: pop(); break;
case BLUE: push(); break;
}