Java enum

Java enum

Enum – „Jesień”, „Jesien”, a może „JESIEN”? 🍁🌰🐿️

W tym materiale przedstawię Ci typ wyliczeniowy, czyli tzw. enum. Jeżeli chcesz zapewnić bezpieczeństwo typu w czasie kompilacji oraz uniknąć przekazywania niechcianych wartości do parametrów, to zachęcam Cię do zapoznania się z tym materiałem. Pokażę Ci jak korzystać z enumów i w jaki sposób czerpać z nich korzyści, aby uniknąć powyższych rozterek.

Enum – Wprowadzenie

Z tego materiału dowiesz się:

  • Czym jest enum?
  • Jak działa konstruktor w klasie enum?
  • Jakie metody udostępnia klasa enum?
  • Jak działa metoda values()?
  • Czym jest EnumSet oraz EnumMap?

Enum

Enum, czyli tzw. typ wyliczeniowy to specjalny typ danych. Typ ten reprezentuje zbiór predefiniowanych stałych.

Deklaracja enum definiuje klasę (zwaną typem enum). Ciało klasy enum może zawierać metody i inne pola – tak jak klasa.

Enumy są używane, gdy znamy wszystkie możliwe wartości w czasie kompilacji, takie jak np. pory roku, kraje, rozmiary ubrań itp.

enum java enum

Enum java – Deklaracja

Deklaracja enum może być wykonana:

  • poza klasą
  • wewnątrz klasy

Pamiętaj! ⚠️ Nie możesz zadeklarować enum wewnątrz metody.

public class Order {


    private OrderStatus status;
    
    public enum OrderStatus {
        IN_DELIVERY,
        DELIVERED,
        CANCELLED
    }


    public boolean isCancelled() {
        if (getStatus() == OrderStatus.CANCELLED) {
            return true;
        }
        return false;
    }
    public OrderStatus getStatus() {
        return status;
    }
 }

Enum java – Zmienne

Zmienne enum są (niejawnie):

  • Finalne (ang. final)
  • Publiczne (ang. public)
  • Statyczne (ang. static)

Enum java – Korzyści 👍

Stałe zdefiniowane w ten sposób:

  • Czynią kod bardziej czytelnym
  • Zapewniają bezpieczeństwo typu w czasie kompilacji – jeśli spróbujesz przekazać wartości inne niż wartości dostępne w klasie enum, kompilator wygeneruje błąd
  • Dokumentują z góry listę akceptowanych wartości
  • Pozwalają uniknąć nieoczekiwanych zachowań spowodowanych przekazaniem nieprawidłowych wartości
  • Wykorzystywane są w konstrukcji switch
public void printDayType(Day day) {

    switch (day) {
        case MONDAY, TUESDAY, WEDNESDAY, THURSDAY:
            System.out.println(day + " is working day");
            break;
        case FRIDAY: 
            System.out.println(day + " is working day, but almost weekend");
            break;
        case SATURDAY, SUNDAY:
            System.out.println(day + " - yeaah it is WEEKEND :)");
            break;
    }
 }

Powrócę tutaj do początkowej rozterki: „Jesień”, „Jesien”, a może „JESIEN”? 🍁🌰🐿️

Wbrew pozorom jedną wartość można przedstawić na wiele różnych sposobów, dlatego warto przyjąć jakieś odgórne zasady – konwencję.

Odgórnie ustalona konwencja w Javie przyjmuje, że nazwa powinna być pisana wielkimi literami, a wyrazy oddzielone od siebie podkreśleniem (ang. screaming snake case).

Enum java – Metody

Kompilator automatycznie dodaje pewne „specjalne” metody, które Twoja klasa enum dziedziczy automatycznie po klasie java.lang.Enum. Do tych „specjalnych” metod można zaliczyć m.in.:

  • values()
  • ordinal()
  • compareTo()
  • name() będący odpowiednikiem toString()
  • valueOf()

Java enum values

Przykładem takiej „specjalnej” metody klasy enum jest statyczna metoda values.

Metoda ta zwraca tablicę zawierającą wszystkie wartości enum w kolejności, w jakiej zostały zadeklarowane.

values() jest powszechnie używane w pętli for-each do iteracji po wartościach typu enum.

 for (Day day : Day.values()) { 
    System.out.println(day); 
 }

Java Enum ordinal()

Metoda ordinal() zwraca pozycje stałej enum. Nie zaleca się jednak korzystania z liczb porządkowych enumów, ponieważ każde dodanie nowej stałej w innym miejscu niż na końcu zmieni wartość ordinal.

Java enum Constructor

W Javie klasa enum może zawierać konstruktor jak zwykła klasa. Taki konstruktor musi być:

  • prywatny (ang. private) – dostępny wewnątrz klasy
  • pakietowy (ang. package-private) – dostępny w ramach pakietu

Konstruktora nie można jednak wywołać ręcznie – zostanie on wywołany automatycznie podczas tworzenia stałych enum.

public enum OrderStatus {
     IN_DELIVERY("Courier is driving to client"),
     DELIVERED("Client confirmed delivery of package"),
     CANCELLED("Client cancelled delivery");


     private final String orderDetails;


     private OrderStatus(String orderDetails) {
         this.orderDetails = orderDetails;
     }


     public String getOrderDetails() {
         return orderDetails;
     }
 }


 class Main{
     public static void main(String[] args) {
         System.out.println(OrderStatus.DELIVERED.getOrderDetails());
     }
 }

Enum java – Dziedziczenie

W Javie klasa enum jest domyślnie końcowa. W związku z tym nie można po niej dziedziczyć.

Również nie jest możliwe rozszerzenie klas enum, ponieważ wszystkie klasy enum w Javie dziedziczą (niejawnie) po klasie java.lang.Enum. Wielokrotne dziedziczenie nie jest dozwolone w Javie.

Możliwe jest natomiast implementowanie przez klasę enum interfejsów.

 public enum OrderStatus implements DeliveryService{

    IN_DELIVERY,
    DELIVERED,
    CANCELLED;
    
    @Override
    public void displayOrderStatus() {
        System.out.println("Current status of your order is: " + this);
    }
 }


 class Main{
    public static void main(String[] args) {
        OrderStatus.DELIVERED.displayOrderStatus();
    }
 }

Java enum – porównywanie wartości – „==” vs. equals vs. Object.equals()

Ponieważ typy enum zapewniają, że tylko jedna instancja stałej istnieje w JVM, można bezpiecznie użyć operatora „==” do porównania dwóch zmiennych.

Należy pamiętać, że korzystając z metody equals w momencie wywołania jej na null, dostaniemy wyjątek NullPointerException (obj1.equals(obj2) – gdzie obj1 jest równy NULL)

Dobrą alternatywą dla equals() jest metoda o tej samej nazwie z biblioteki Objects (Objects.equals()), która umożliwia porównywanie również wartości nullowych bez ryzyka pojawienia się wyjątku NullPointerException.

@Test
public void objectsEqualsShouldNotThrowNullPointerException(){
    assertFalse(Objects.equals(null, "Kasia"));
}

➡ ZOBACZ 👉: hashCode i equals – co grozi Ci za złamanie kontraktu między metodami equals i hashCode?

EnumSet

EnumSet jest wyspecjalizowaną implementacją Set, która jest przeznaczona do użycia z typami Enum.

EnumSet bardziej wydajnie przechowuje wartości enum w porównaniu do HashSet.

Możliwe jest stworzenie nowego EnumSeta m.in. poprzez:

  • of()
  • all()
  • range()
 EnumSet<OrderStatus> allStatuses = EnumSet.allOf(OrderStatus.class);
 
 EnumSet<OrderStatus> deliveryStatuses = EnumSet.of(OrderStatus.IN_DELIVERY, OrderStatus.DELIVERED);
 
 EnumSet<OrderStatus> finalStatuses = EnumSet.range(OrderStatus.DELIVERED, OrderStatus.CANCELLED);

EnumMap

EnumMap jest wyspecjalizowaną implementacją Mapy przeznaczoną do użycia ze stałymi enum jako kluczami.

EnumMap bardziej wydajnie przechowuje wartości enum w porównaniu do HashMap.

 EnumMap<OrderStatus, String> statusesWithDetails = new EnumMap<>(OrderStatus.class);
 statusesWithDetails.put(OrderStatus.CANCELLED, "Client cancelled delivery");

Enum – Typ wyliczeniowy – Podsumowanie

W ramach tego materiału dowiedzieliśmy się, czym jest enum. Bliżej zapoznaliśmy się ze strukturą klasy enum i jej możliwościami. Jeżeli chcesz kontynuować swoją przygodę z Javą i poznać inne struktury, które oferuję ten język programowania – to zapraszam do zapoznania się z różnymi tematami z serii o Javie.

ZOBACZ 👉: Kurs Java | Darmowy Kurs Programowania w Javie

Kierunek Java

W serii o Javie zapoznajesz się z podstawowymi tematami o Javie. Jeżeli chcesz bardziej kompleksowo zagłębić się w temat Javy, poczytać, posłuchać o Javie, to zachęcam Cię do zapoznania się z moim kursem „Kierunek Java”:

➡ ZOBACZ 👉: Kierunek Java


Jak zostać programistą

8 rzeczy, które musisz wiedzieć, żeby dostać pracę jako programista.

Jak zostać programistą
No comments
Share:

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *