
Wymień metody typu wyliczeniowego i opisz krótko ich przeznaczenie
W typie wyliczeniowym znajdziemy następujące metody:
- name(),
- ordinal(),
- values(),
- valueOf(String name).
Przypuśćmy, że mamy typ wyliczeniowy Gender:
package org.blog; public enum Gender { MALE, FEMALE }
name()
Metoda zwraca nazwę obiektu, czyli wywołując:
System.out.println(Gender.MALE.name());
Otrzymamy:
MALE
ordinal()
Ze względu, że każdy obiekt typu wyliczeniowego ma przypisany swój numer to możemy go odczytać właśnie przy użyciu metody ordinal().
Czyli taki kod:
System.out.println(Gender.FEMALE.ordinal());
Zwróci nam:
1
Otrzymaliśmy 1, ponieważ numeracja rozpoczyna się klasycznie jak to bywa w programowaniu od 0.
values()
Metoda values() zwraca nam tablicę obiektów danego typu wyliczeniowego.
Gender [] genders = Gender.values();
Dla pewności możemy je wyświetlić:
for (Gender gender: genders) { System.out.println(gender); }
A wtedy otrzymamy:
MALE FEMALE
valueOf(String name)
Metoda valueOf umożliwia nam otrzymanie obiektu typu wyliczeniowego na podstawie nazwy w postaci Stringa.
Gender male = Gender.valueOf("MALE");
Jednak trzeba pamiętać, że wielkość liter ma znaczenie. Przy takim wywołaniu:
Gender maleLowerCase = Gender.valueOf("male");
Otrzymamy wyjątek IllegalArgumentException:
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant org.blog.Gender.male
Który informuje nas, że nie można znaleźć obiektu dla podanej nazwy.
toString()
O ile metoda toString jest domyślnie w każdym obiekcie (pochodzi z klasy Object) to typie wyliczeniowym ma ona domyślnie inne zachowanie niż w każdym innym obiekcie.
Normalny obiekt bez przeciążonej metody toString() zwróci nam m.in. swój adres w pamięci:
org.blog.Main$User@6d6f6e28
Za to typ wyliczeniowy zwróci swoją nazwę – tak jak metoda name():
System.out.println(Gender.MALE.toString());
Dla potwierdzenie efekt w konsoli:
MALE
Bonus
Metody name i ordinal są finalne, tzn. że nie można ich przysłonić. Łatwo to sprawdzić.
package org.blog; public enum Gender { MALE, FEMALE; @Override public String name() { return super.name().toLowerCase(); } @Override public int ordinal() { return super.ordinal() + 1; } }
Metody values() oraz valueOf(String name) są statyczne, więc jest oczywiste, że nie mamy możliwości ich przysłonięcia.
Kompilując powyższy kod otrzymamy taki błąd:
Error:(11, 19) java: name() in org.blog.Gender cannot override name() in java.lang.Enum overridden method is final Error:(16, 16) java: ordinal() in org.blog.Gender cannot override ordinal() in java.lang.Enum overridden method is final
Czasami potrzebujemy w inny sposób parsować Stringa na dany obiekt typu wyliczeniowego, a już wiemy, że przysłonięcie tej metody jest niemożliwe. Jak sobie można się z tym uporać?
Bezpośrednio w danym enumie można zaimplementować statyczną metodę, np.:
public static Gender getGenderByValue(String value) { String valueLowerCase = value.toLowerCase(); return Arrays.asList(values()).stream() .filter(gender -> gender.name().toLowerCase().equals(valueLowerCase)) .findFirst() .orElseThrow(IllegalArgumentException::new); }
Mając napisaną taką metodę możemy już się nie martwić wielkością znaków:
System.out.println(Gender.getGenderByValue("male"));
Jedynym problemem jest to, że nigdy nie możemy wymusić używania tej metody zamiast valueOf co w przyszłości może spowodać problemy w aplikacji.