Myślę, że w pewnym stopniu była to prawdopodobnie arbitralna decyzja oparta na typowym zastosowaniu przełącznika.
Przełącznik można zasadniczo zaimplementować na dwa sposoby (lub w zasadzie kombinację): dla niewielkiej liczby przypadków lub tych, których wartości są szeroko rozproszone, przełącznik zasadniczo staje się odpowiednikiem serii if na zmiennej tymczasowej ( włączaną wartość można ocenić tylko raz). W przypadku umiarkowanej liczby przypadków, które mają mniej więcej następującą po sobie wartość, używana jest tablica przełączników (instrukcja TABLESWITCH w języku Java), dzięki czemu lokalizacja, do której należy przeskoczyć, jest efektywnie wyszukiwana w tabeli.
Każda z tych metod mogłaby zasadniczo używać wartości długiej zamiast liczby całkowitej. Ale myślę, że prawdopodobnie była to tylko praktyczna decyzja, aby zrównoważyć złożoność zestawu instrukcji i kompilatora z rzeczywistymi potrzebami: przypadki, w których naprawdę trzeba przełączyć się na długi czas, są na tyle rzadkie, że dopuszczalne jest ponowne napisanie jako serię instrukcji IF lub obejść w inny sposób (jeśli długie wartości, o których mowa, są blisko siebie, możesz w kodzie Java przełączyć się na wynik int, odejmując najniższą wartość).
Ponieważ nie zaimplementowali niezbędnych instrukcji w kodzie bajtowym i naprawdę nie chcesz pisać tak wielu przypadków, bez względu na to, jak "gotowy do produkcji" jest twój kod ...
[EDYTUJ: Wyciąg z komentarzy do tej odpowiedzi, z kilkoma dodatkami w tle]
Mówiąc dokładniej, 2³² to wiele przypadków, a każdy program z metodą wystarczająco długą, by pomieścić więcej, będzie całkowicie przerażający! W dowolnym języku. (Najdłuższa funkcja, jaką znam w każdym kodzie w jakimkolwiek języku, to nieco ponad 6k SLOC - tak, jest duża
switch
- i naprawdę nie da się nią zarządzać.) Jeśli naprawdę utkniesz w miejscu, wlong
którym powinieneś mieć tylkoint
lub mniej wtedy masz dwie prawdziwe alternatywy.Użyj
long
innego wariantu tematu funkcji skrótu, aby skompresować plik do plikuint
. Najprostszym, do użycia tylko wtedy, gdy masz zły typ, jest po prostu rzucanie! Bardziej przydatne byłoby zrobienie tego:(int) ((x&0xFFFFFFFF) ^ ((x >>> 32) & 0xFFFFFFFF))
przed włączeniem wyniku. Będziesz musiał dowiedzieć się, jak przekształcić przypadki, przeciwko którym testujesz. Ale tak naprawdę to nadal jest okropne, ponieważ nie rozwiązuje prawdziwego problemu wielu przypadków.
Znacznie lepszym rozwiązaniem, jeśli pracujesz z bardzo dużą liczbą przypadków, jest zmiana projektu na użycie
Map<Long,Runnable>
czegoś podobnego, aby sprawdzić, jak wysłać określoną wartość. Pozwala to na podzielenie spraw na wiele plików, co jest znacznie łatwiejsze do zarządzania, gdy liczba przypadków rośnie, chociaż organizowanie rejestracji wielu zaangażowanych klas implementacyjnych staje się bardziej skomplikowane (adnotacje mogą pomóc, umożliwiając utworzyć kod rejestracyjny automatycznie).FWIW, zrobiłem to wiele lat temu (przestawiliśmy się na nowo wydaną J2SE 1.2 częściowo przez projekt) podczas budowania niestandardowego silnika kodu bajtowego do symulacji sprzętu na masową skalę (nie, ponowne użycie JVM nie byłoby odpowiednie ze względu na radykalnie różne modele wartości i wykonania) i ogromnie uprościło kod w stosunku do dużego
switch
, którego używała wersja C kodu.Aby powtórzyć wiadomość, którą można zabrać do domu, chęć
switch
włączenia along
jest wskazówką, że albo masz nieprawidłowe typy w swoim programie, albo budujesz system z tak dużą różnorodnością, że powinieneś używać klas. W obu przypadkach czas na przemyślenie.źródło
Map<Long,Runnable>
aby rozwiązać problem w zupełnie inny sposób. :-)switch
? Chęć wybrania skończonego zestawu tak wielu elementów po prostu wskazuje na błąd w podstawowym projekcie programu. To, że ludzie o to proszą, oznacza jedynie, że ** źle zaprojektowali swój projekt .long
liczbę wierszy, potrzebuję tylko 4. Jest to przypadek, w którymlong
otrzymałem informację, która wskazuje, który wiersz jest wykonywany, i muszę zrobić różne rzeczy w zależności od tego, który to wiersz. Myślę, że mógłbym rzutować na int, ale ułatwiłoby mi to życie, gdybym mógł po prostuswitch
włączyć tę zmienną. Obecnie używam tylko ciągu znakówif
ielse if
.long
nie oznacza, że zamierzasz sprawdzić wszystkie możliwości, tak jak posiadanieint
lubString
nie oznacza, że też. Oznacza to, że wartości, które masz, które mogą być garstką, mają duży zakres . Możesz sprawdzić kilka prostych przypadków i zająć siędefault
resztą. Konieczność wykonywania zmian i rzutów oznacza, że ryzykujesz utratę danych. Podsumowując, jest to zła decyzja dotycząca projektu Java, a nie problem użytkownika.Ponieważ indeks tabeli przeglądowej musi mieć 32 bity.
źródło
switch
nie trzeba koniecznie implementować tabeli przeglądowej.Długi, w architekturze 32-bitowej, jest reprezentowany przez dwa słowa . Teraz wyobraź sobie, co mogłoby się stać, gdyby z powodu niewystarczającej synchronizacji wykonanie instrukcji switch obserwowało długi z jego wysokimi 32 bitami z jednego zapisu i 32 niskimi z innego! Mógłby spróbować ... kto wie gdzie! Zasadniczo gdzieś przypadkowo. Nawet gdyby oba zapisy reprezentowały ważne przypadki dla instrukcji przełącznika, ich zabawna kombinacja prawdopodobnie nie prowadziłaby ani do pierwszego, ani do drugiego - lub, co gorsza, mogłaby prowadzić do innego ważnego, ale niezwiązanego z nim przypadku!
Przynajmniej w przypadku typu int (lub mniejszych typów), bez względu na to, jak bardzo zepsujesz, instrukcja switch przynajmniej odczyta wartość, którą ktoś faktycznie napisał , zamiast wartości „z powietrza”.
Oczywiście nie znam faktycznego powodu (minęło ponad 15 lat, nie zwracałem na to uwagi tak długo!), Ale jeśli zdasz sobie sprawę, jak niebezpieczny i nieprzewidywalny może być taki konstrukt, zgodzisz się, że jest to zdecydowanie bardzo dobry powód, aby nigdy nie włączać długich pozycji (i tak długo, jak zamierzano - będą maszyny 32-bitowe, ten powód pozostanie ważny).
źródło
if
również i wynik byłby równie zły: zły wynik ~> niewłaściwa gałąź. Tworzenie długiif
-else
-if
łańcuch zamiastswitch
faktycznie doprowadzić do dokładnie tego samego rezultatu.