Kiedy zaczynałem programować w Javie, frustrowało mnie to, że instrukcje switch nie miały ciągów. Następnie, korzystając z Enums, zdałem sobie sprawę z korzyści, jakie z nich czerpiesz, zamiast przekazywać surowe wartości - bezpieczeństwo typu (co ułatwia refaktoryzację) oraz przejrzystość dla innych programistów.
Próbuję wymyślić sytuację, w której w SE7 zdecyduję się teraz użyć przełącznika z ciągami jako wejściami, a nie z Enums. Jeśli są one implementowane poprzez przełączanie całych łańcuchów (np. Zamiast dopasowań częściowych lub wyrażeń regularnych), wydaje się, że nie oferuje mniejszego powodu do zmiany kodu.
A dzięki narzędziom IDE i stosunkowi kodowania do odczytu i zapisu znacznie chętniej wygenerowałbym dodatkowe Enum niż przekazywanie wartości ciągów.
Jakie korzyści przynoszą nam jako programistom? Mniej płyty kotła?
Nie wydaje się, żeby język wołał o tę funkcję. Chociaż może istnieje przypadek użycia, który przeoczam.
źródło
Odpowiedzi:
O ile mogę stwierdzić, pytanie brzmi: dlaczego zawijanie stałych String do enum nie zostało uznane za wystarczające do zaspokojenia potrzeb użytkowników języka. Zostało to rozwiązane w oficjalnej propozycji funkcji ogłoszonej na liście mailingowej JDK 7 (Project Coin).
Według mojej lektury propozycji odrzucono alternatywę używania wyliczeń, ponieważ wprowadza ona typy wzdęć. Dla Twojej wygody odpowiednia część wniosku jest cytowana poniżej, a oświadczenie odnoszące się do wyliczeń pogrubione :
źródło
Oprócz zwiększenia czytelności kodu, istnieje potencjalny wzrost wydajności w
if/else if
porównaniu z porównaniami. To, czy zmiana jest opłacalna, zależy od liczby porównań. Przełącznik łańcuchowy będzie emitowany jako dwie oddzielne instrukcje przełączania. Pierwszy działa na kody hash, więc wydaje się byćlookupswitch
, ostatecznie uzyskującO(log n)
złożoności. Drugi jest zawsze idealnyO(1)
tableswitch
, więc połączona złożoność jest nadalO(log n)
. Pojedynczy, liniowy łańcuchif/else if
instrukcji dałby nieco gorsząO(n)
złożoność.Jeśli porównujesz więcej niż, powiedzmy, trzy ciągi,
switch
to prawdopodobnie jest bardziej czytelny i zwarty. Prawdopodobnie będzie działał lepiej, chociaż nie zauważysz różnicy, chyba że wykonasz dużą liczbę porównań na ścieżce kodu.źródło
if/else
blokową złą praktykę, ale w tej chwili nie miałbym zbyt wiele powodów, by z niej korzystać.Przełącznik ciągów znaków może być używany, gdy twoje
enum
wartości pochodzą z zewnątrz, tj. Są przechowywane w bazie danych.Kolejną godną uwagi rzeczą w JDK 7
switch
jest to, że jest znacznie bardziej wydajny niżif-else
konstrukcje.Dobrym przykładem użycia dla szybkich ciągów znaków
switch
może być parsowanie strumienia JSON / XML, gdy trzeba dokonać wielu przełączeń na typach węzłów i atrybutów. Nie mogę wymyślić lepszej opcji.źródło
enum
w tym przypadku można użyć z powodu statycznej natury Javy. Kiedy to pisałem, myślałem oRole
bibliotece bezpieczeństwa, która zwykle jest udostępniana jako klasa i nie można jej umieścićenum
. Innym przypadkiem jest dynamicznie kompilowany kod Java / Groovy - w tej rzadkiej sytuacji lepszym rozwiązaniem mogą być przełączniki łańcuchowe.Prostota
Obsługa ciągu w przełączniku jest przydatna do przetwarzania danych bez konwersji na wyliczenie lub
if-else
logikę. Czasami łatwiej jest włączyć String.Od propozycji funkcji na liście mailingowej JDK 7 (Project Coin) ( odpowiedź @gnat )
Wersja If-Else
To jest krótkie, ale wiele z nich
if's
jest trudnych do odczytania. I to jest powolne.Wersja enum
Należy zdefiniować wyliczenia, to dobrze, ale czasami nie jest potrzebne.
Przetwarzanie jak zwykle
JDK 7 - Ciągi w wersji instrukcji switch
Możemy przetwarzać bez konwersji i definiowania dodatkowych typów.
źródło
Większość ulepszeń w dowolnym języku ma na celu ułatwienie odczytu kodu. Wolę czytelny kod od wyszukanego każdego dnia.
Możesz w to nie wierzyć, ale spróbuj:
źródło
Wyliczenia są świetne i powinieneś ich używać zamiast Strun, jeśli masz taką możliwość. Ale są chwile, kiedy po prostu nie możesz, na przykład, gdy musisz pracować z jakimś zewnętrznym obiektem pochodzącym spoza Javy. Wyobraź sobie, że musisz coś przeanalizować. Na przykład odpowiedź serwera, konfiguracja, plik dziennika lub coś podobnego: masz wiele opcji, których szukasz, i nie ma możliwości, aby były to wyliczenia. Więc w Javie <7 utknąłbyś z wieloma
W tym przypadku możesz nadal używać wyliczeń, po prostu próbując uzyskać je według nazw i / lub zapewniając niestandardową procedurę String-> Enum, ale czasami jest to niemożliwe lub po prostu niepraktyczne (tj. Gdy będziesz musiał utworzyć zbyt wiele wyliczeń)
TLDR : absolutnie powinieneś używać Enums, gdy pracujesz wyłącznie z kodem Java, ale nie zawsze jest to możliwe w przypadku obiektów zewnętrznych. Mam nadzieję, że moje wyjaśnienie ma sens.
źródło
if
sprawozdaniu, to należy owijając go w każdym razie , co oznacza, że można nadal używać teksty stałe lub wzorzec komendy, itpNie zgadzam się z opinią, że jest to czystszy i czytelniejszy kod, gdy używasz go
Strings
w instrukcjach switch i uważam, że to zła praktyka programowania. Jeśli zmienisz wartość, której używasz do przechowywania, musisz ją zmienić przy każdym przełączeniu lub w przypadku wystąpienia if-elseif. Nie jest to dobre, ponieważ umieszczasz wartości zakodowane w każdym pliku kodu. Co zrobisz, jeśli pewnego dnia zdecydujesz się zmienić jedną z tych wartości zakodowanych na stałe? Wyszukaj i zamień każdą jego kopię?Jeśli masz pewne zakodowane wartości, które wykonujesz w instrukcjach if-elseif, używanie dla nich stałych wartości pierwotnych jest znacznie lepsze niż w Javie 1.5 tylko dlatego, że zapewnia bezpieczeństwo typu.
OK, pojawią się sytuacje, w których otrzymasz wartości ciągu (z żądania HTTP, plików itp.), A konwersja ich do wartości pierwotnych jest uciążliwa. Ale
Enum
w tym momencie wykonujemy dobrą robotę. Ponieważ jeśli chcesz zmienić wartość przechowywaną w Enum, po prostu zmień ją podczas deklarowania. Nie musisz zmieniać niczego w kodzie. (Oczywiście musisz zmienić wartości zapisane gdzie indziej).Oczywiście, jeśli tylko implementujesz brudny i leniwy kod, jest idealny. Nie chcesz angażować się w kodowanie wielu
Enum
s, ale w złożone oprogramowanie na dużą skalę, które cię zabije.źródło
Jeśli wiesz, jakie informacje nadchodzą i że może to być tylko 5 stanów, użyj
Enum
. Jeśli jednak możliwe stany mogą być większe niż 9000, a wystarczy tylko znaleźć 42, to użycie przełącznika jest lepsze, ponieważ nie chcesz wpisywać wszystkich tych stanów.Zazwyczaj Enum jest wyborem w większości przypadków, chyba że możliwe stany są nieznane lub jest ich wiele i zależy ci tylko na kilku.
Ale dlaczego wprowadzili to teraz? To była tylko zmiana, która pozwoliła na czystszy kod.
W wersji 1.5 pozwoliły również na tworzenie niestandardowych obiektów dla Enums.
źródło
default
miejscuswitch
wkracza gra. Nie wiem, czy możesz mieć stan domyślnyEnum
, chyba że wprowadzisz stan domyślny, ale wtedy ten kod jest po prostu rozdęty, podczas gdyswitch
użycie programu jest znacznie prostsze.UNKNOWN
stan na Enum jest rozdęty, aledefault
przypadek na przełączniku tak nie jest.