JavaRush /Blog Java /Random-PL /Wyliczenia w Javie (java enum)
articles
Poziom 15

Wyliczenia w Javie (java enum)

Opublikowano w grupie Random-PL
Podczas programowania często spotykamy się z koniecznością ograniczenia zbioru prawidłowych wartości dla określonego typu danych. Na przykład dzień tygodnia może mieć 7 różnych wartości, miesiąc roku może mieć 12, a pora roku może mieć 4. Aby rozwiązać takie problemy, wiele języków programowania z typem statycznym udostępnia specjalny typ danych - wyliczenie ( enum). Wyliczenie nie pojawiło się od razu w Javie. enumPocząwszy od wersji 1.5 wprowadzono konstrukcję języka specjalistycznego . Do tego momentu programiści używali innych metod implementacji wyliczeń. Wyliczenia w Javie (java enum) - 1

konstrukcja wyliczeniowa

Zacznijmy od przykładu. Opiszmy enumtyp danych do przechowywania sezonu za pomocą:
enum Season { WINTER, SPRING, SUMMER, AUTUMN }
Cóż, prosty przykład jego użycia:
Season season = Season.SPRING;
if (season == Season.SPRING) season = Season.SUMMER;
System.out.println(season);
W wyniku czego na konsoli zostanie wydrukowana wartość SUMMER . Myślę, że przykład jest oczywisty i nie wymaga objaśnień.

Enum jest klasą

Deklarując enum, domyślnie tworzymy klasę pochodną java.lang.Enum. Konwencjonalnie konstrukcja enum Season { ... }jest równoważna class Season extends java.lang.Enum { ... }. I chociaż kompilator nie pozwala nam jawnie dziedziczyć po java.lang.Enumnas, nadal łatwo jest sprawdzić, czy enumjest dziedziczony za pomocą reflection:
System.out.println(Season.class.getSuperclass());
Na konsoli wyświetli się:
class java.lang.Enum
Rzeczywiste dziedziczenie wykonuje za nas automatycznie kompilator Javy. Następnie zgódźmy się wywołać klasę stworzoną przez kompilator w celu implementacji wyliczenia jako -class enum, a możliwe wartości typu wyliczeniowego jako enumelementy -a.

Elementy wyliczeniowe są instancjami enumklasy -, które są dostępne statycznie

Elementy enum Season (WINTER, SPRING и т.д.)są statycznie dostępnymi instancjami enumklasy - Season. Ich statyczna dostępność pozwala na dokonywanie porównań za pomocą referencyjnego operatora porównania ==. Przykład:
Season season = Season.SUMMER;
if (season == Season.AUTUMN) season = Season.WINTER;

Nazwa i numer seryjny elementu wyliczeniowego

Jak wspomniano wcześniej, każda enum-class dziedziczy java.lang.Enum, która zawiera szereg metod przydatnych dla wszystkich wyliczeń. Przykład:
Season season = Season.WINTER;
System.out.println("season.name()=" + season.name() + " season.toString()=" + season.toString() + " season.ordinal()=" + season.ordinal());
Dane wyjściowe będą następujące:
season.name()=WINTER season.toString()=WINTER season.ordinal()=0
Metody name()i toString()są pokazane tutaj ordinal(). Semantyka metod jest oczywista. Należy zaznaczyć, że metody te enumsą dziedziczone z klasy java.lang.Enum. Pobieranie elementu enumna podstawie jego nazwy w postaci ciągu znaków. Dość często pojawia się zadanie pobrania elementu enumna podstawie jego reprezentacji w postaci ciągu znaków. W tym celu w każdej enumklasie kompilator automatycznie tworzy specjalną metodę statyczną: public static EnumClass valueOf(String name), która zwraca element wyliczeniowy EnumClasso nazwie równej name. Przykład użycia:
String name = "WINTER";
Season season = Season.valueOf(name);
W wyniku wykonania kodu zmienna sezon będzie równa Season.WINTER. Należy pamiętać, że jeśli element nie zostanie znaleziony, zostanie zgłoszony wyjątek IllegalArgumentException , a jeśli jest namerówny null, zostanie zgłoszony wyjątek NullPointerException . Swoją drogą, często się o tym zapomina. Z jakiegoś powodu wielu jest głęboko przekonanych, że jeśli funkcja przyjmuje jeden argument i pod pewnymi warunkami zgłasza wyjątek IllegalArgumentException , to przekazując go tam , nullz pewnością zostanie zgłoszony również wyjątek IllegalArgumentException . Ale to nie ma znaczenia. Kontynuujmy. Pobieranie wszystkich elementów wyliczenia Czasami trzeba uzyskać listę wszystkich elementów enumklasy - w czasie wykonywania. W tym celu enumkompilator tworzy metodę w każdej -klasie public static EnumClass[] values(). Przykład użycia:
System.out.println(Arrays.toString(Season.values()));
Otrzymujemy dane wyjściowe:
[WINTER, SPRING, SUMMER, AUTUMN]
Należy zauważyć, że w klasie nie zdefiniowano ani metody valueOf(), ani metody . Zamiast tego są one automatycznie dodawane przez kompilator podczas kompilacji klasy -. Dodawanie własnych metod do klasy -Masz możliwość dodania własnych metod zarówno do klasy -jak i jej elementów: To samo, ale z polimorfizmem: Ostatni przykład demonstruje użycie dziedziczenia w . Więcej na ten temat później. Dziedziczenie w Javie pozwala na implementację hierarchii klas, której obiekty tworzone są w jednej instancji i są dostępne statycznie. W tym przypadku elementy mogą zawierać własne konstruktory. Podajmy przykład: Tutaj deklarujemy wyliczenie z trzema elementami i . Kompilator utworzy następujące klasy i obiekty: values()java.lang.EnumenumenumenumWyliczenia w Javie (java enum) - 2Wyliczenia w Javie (java enum) - 3enumenumenumenumWyliczenia w Javie (java enum) - 4TypeINTINTEGERSTRING
  • Type- klasa wywodząca się zjava.lang.Enum
  • INT— przedmiot I klasy wywodzący się zType
  • INTEGER— przedmiot II klasy wywodzący się zType
  • STRING— przedmiot 3. klasy wywodzący się zType
Zostaną utworzone trzy klasy pochodne za pomocą metody polimorficznej Object parse(String)i konstruktora Type(..., boolean). Jednocześnie obiekty klas INTi istnieją w jednym egzemplarzu i są dostępne statycznie INTEGER. STRINGMożesz to zweryfikować:
System.out.println(Type.class);
System.out.println(Type.INT.getClass() + " " + Type.INT.getClass().getSuperclass());
System.out.println(Type.INTEGER.getClass() + " " + Type.INTEGER.getClass().getSuperclass());
System.out.println(Type.STRING.getClass()  + " " + Type.STRING.getClass().getSuperclass());
Otrzymujemy następujące dane wyjściowe:
class Type
class Type$1 class Type
class Type$2 class Type
class Type$3 class Type
Można zauważyć, że kompilator utworzył klasę Typei 3 nestedklasy wywodzące się z Type.

Zdekompilowana klasa wyliczeniowa z dziedziczeniem

Na potwierdzenie powyższego prezentujemy również wynik dekompilacji wyliczenia Typez powyższego przykładu: Wyliczenia w Javie (java enum) - 5

Wyliczenia i polimorfizm parametryczny

Czytelnik może się zastanawiać: „ Dlaczego powyższe wyliczenie typów nie używa typów ogólnych? ” Faktem jest, że w Javie używanie nazw generycznych jest enumzabronione. Zatem poniższy przykład nie zostanie skompilowany:
enum Type<T> {}

Dalsze badanie

Aby lepiej zrozumieć działanie wyliczeń w Javie, polecam zapoznać się z kodem źródłowym klasy java.lang.Enum, a także skorzystać z dekompilatora Jad w celu przestudiowania wygenerowanego kodu. Co więcej, przestudiowanie kodu źródłowego biblioteki Java jest absolutnie konieczne, aby zrozumieć, jak wiele mechanizmów działa w Javie i jest przydatne jako punkt odniesienia w projektowaniu obiektowym. Link do oryginalnego źródła: http://alexander.lds.lg.ua/
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION