CodeGym /Blog Java /Poland /Klasa Enum w Javie
Autor
Milan Vucic
Programming Tutor at Codementor.io

Klasa Enum w Javie

Opublikowano w grupie Poland
Cześć! W tym artykule opowiemy o typie wyliczeniowym Java Enum. Wyobraź sobie, że otrzymujesz następujące zadanie: utwórz klasę, która implementuje dni tygodnia. Na pierwszy rzut oka wydaje się to dość proste. Kod wyglądałby mniej więcej tak:

public class DayOfWeek {

   private String title;

   public DayOfWeek(String title) {
       this.title = title;
   }

   public static void main(String[] args) {
       DayOfWeek dayOfWeek = new DayOfWeek("Saturday");
       System.out.println(dayOfWeek);
   }

   @Override
   public String toString() {
       return "DayOfWeek{" +
               "title='" + title + '\'' +
               '}';
   }
}
Wszystko wydaje się w porządku, ale jest jeden problem: do konstruktora klasy DayOfWeek możesz przekazać dowolny tekst. Oznacza to, że możesz utworzyć dzień tygodnia o nazwie "Żaba", "Chmura" lub "azaza322". Oczywiście nie jest to zachowanie, którego się spodziewamy, ponieważ w rzeczywistości istnieje tylko 7 dni tygodnia, a każdy z nich ma swoją nazwę. Dlatego naszym zadaniem jest ograniczyć jakoś zakres możliwych wartości dla klasy DayOfWeek. Zanim pojawiła się Java 1.5, programiści musieli tworzyć własne rozwiązania tego problemu, ponieważ język nie posiadał gotowego rozwiązania. W tamtych czasach ograniczenie liczby dopuszczalnych wartości realizowało się w następujący sposób:

public class DayOfWeek {

   private String title;

   private DayOfWeek(String title) {
       this.title = title;
   }

   public static DayOfWeek SUNDAY = new DayOfWeek("Sunday");
   public static DayOfWeek MONDAY = new DayOfWeek("Monday");
   public static DayOfWeek TUESDAY = new DayOfWeek("Tuesday");
   public static DayOfWeek WEDNESDAY = new DayOfWeek("Wednesday");
   public static DayOfWeek THURSDAY = new DayOfWeek("Thursday");
   public static DayOfWeek FRIDAY = new DayOfWeek("Friday");
   public static DayOfWeek SATURDAY = new DayOfWeek("Saturday");

   @Override
   public String toString() {
       return "DayOfWeek{" +
               "title='" + title + '\'' +
               '}';
   }
}
Na co należy zwrócić uwagę:
  • Konstruktor jest prywatny. Jeżeli konstruktor jest oznaczony modyfikatorem private, nie można użyć go do utworzenia obiektu. A ponieważ ta klasa ma tylko jeden konstruktor, obiekty DayOfWeek nigdy nie zostaną utworzone.

    
    	public class Main {
    
       		public static void main(String[] args) {
          
           			DayOfWeek sunday = new DayOfWeek(); // Error!
       		}
    }
    
  • Oczywiście klasa posiada odpowiednią liczbę obiektów public static, które zostały poprawnie zainicjalizowane (przy użyciu poprawnych nazw dni tygodnia).

    To pozwala używać tych obiektów w innych klasach.

    
    	public class Person {
    
       		public static void main(String[] args) {
    
           			DayOfWeek sunday = DayOfWeek.SUNDAY;
    
           			System.out.println(sunday);
      		 }
    }
    

    Wyjście:

    DayOfWeek{tytuł = 'Niedziela'}

Takie podejście w dużej mierze rozwiązuje problem. Mamy do dyspozycji 7 dni tygodnia i nikt nie może utworzyć nowych. Takie rozwiązanie zaproponował Joshua Bloch w swojej książce Java. Efektywne programowanie. Nawiasem mówiąc, to świetna książka i obowiązkowa pozycja dla każdego programisty Java. W Java 1.5 pojawiło się gotowe rozwiązanie na takie sytuacje: typ wyliczeniowy Java Enum. Enum w Javie to również klasa. Jest specjalnie "dostrojona" do rozwiązywania tego typu problemów, czyli tworzenia pewnego ograniczonego zestawu wartości. Twórcy Javy mogli korzystać z gotowych przykładów (np. w C istniał już typ enum), zatem mogli stworzyć najlepsze rozwiązanie.

Czym jest Enum w Javie?

Wróćmy do naszego przykładu DayOfWeek:

public enum DayOfWeek {

   SUNDAY,
   MONDAY,
   TUESDAY,
   WEDNESDAY,
   THURSDAY,
   FRIDAY,
   SATURDAY
}
Teraz wygląda to o wiele prościej :) Wewnętrznie nasz Enum ma 7 stałych statycznych. I to jest coś, czego możemy używać w implementacji programu. Napiszmy na przykład program, który sprawdza, czy uczeń musi dziś iść do szkoły. Nasz student będzie miał plan zajęć reprezentowany przez klasę StudentSchedule:

public class StudentSchedule {

   private DayOfWeek dayOfWeek;
   // ... other fields


   public DayOfWeek getDayOfWeek() {
       return dayOfWeek;
   }

   public void setDayOfWeek(DayOfWeek dayOfWeek) {
       this.dayOfWeek = dayOfWeek;
   }
}
Zmienna dayOfWeek w obiekcie harmonogramu określa, który dzień jest dzisiaj. A oto nasza klasa Student:

public class Student {

   private StudentSchedule schedule;
   private boolean goToSchool;

   public void wakeUp() {
      
       if (this.schedule.getDayOfWeek() == DayOfWeek.SUNDAY) {
           System.out.println("Hooray, you can sleep more!");
       } else {
           System.out.println("Damn, time for school again :(");
       }
   }
}
W metodzie wakeUp() używamy Enum Java, aby określić, co student powinien zrobić. Nie podaliśmy nawet szczegółów dotyczących każdego pola w DayOfWeek i nie musimy tego robić: to jak mają działać dni tygodnia jest oczywiste. Jeśli użyjemy tego w obecnej formie, każdy programista zrozumie co dzieje się w naszym kodzie. Innym przykładem wygody Enum jest to, że jego stałe mogą być używane w instrukcji switch. Napiszmy na przykład program ze ścisłą dietą, w której do każdego dnia przypisane są dania:

public class VeryStrictDiet {
   public void takeLunch(DayOfWeek dayOfWeek) {
       switch (dayOfWeek) {
           case SUNDAY:
               System.out.println("Sunday Dinner! You can even enjoy something a little sweet today.");
               break;
           case MONDAY:
               System.out.println("Lunch for Monday: chicken noodle soup!");
               break;
           case TUESDAY:
               System.out.println("Tuesday, today it's celery soup :(");
               break;
               //... and so on to the end
       }
   }
}
To jedna z zalet typu wyliczeniowego Enum w stosunku do starego rozwiązania używanego przed Javą 1.5 — stare rozwiązanie nie mogło być używane w poleceniu switch. Co jeszcze musisz wiedzieć Enum? Enum to prawdziwa klasa ze wszystkimi możliwościami, które z tego wynikają. Na przykład, jeżeli obecna implementacja jest niewystarczająca, możesz dodać do DayOfWeek zmienne, konstruktory i metody:

public enum DayOfWeek {
  
   SUNDAY ("Sunday"),
   MONDAY ("Monday"),
   TUESDAY ("Tuesday"),
   WEDNESDAY ("Wednesday"),
   THURSDAY ("Thursday"),
   FRIDAY ("Friday"),
   SATURDAY ("Saturday");

   private String title;

   DayOfWeek(String title) {
       this.title = title;
   }

   public String getTitle() {
       return title;
   }

   @Override
   public String toString() {
       return "DayOfWeek{" +
               "title='" + title + '\'' +
               '}';
   }
}
Teraz nasze stałe wyliczeniowe (Enum) mają pole title, getter i przesłoniętą metodę toString. W porównaniu do zwykłych klas Enum ma jedno poważne ograniczenie — nie można go dziedziczyć. Dodatkowo typy wyliczeniowe mają specjalne metody:
  • values(): zwraca tablicę wszystkich wartości w Enum:

    
    public static void main(String[] args) {
       		System.out.println(Arrays.toString(DayOfWeek.values()));
    }
    

    Wyjście:

    [DayOfWeek{tytuł = 'Niedziela'}, DayOfWeek{tytuł = 'Poniedziałek'}, DayOfWeek{tytuł = 'Wtorek'}, DayOfWeek{tytuł = 'Środa'}, DayOfWeek{tytuł = 'Czwartek'}, DayOfWeek{tytuł = 'Piątek'}, DayOfWeek{tytuł = 'Sobota'}]
  • ordinal(): zwraca liczbę porządkową stałej. Numeracja zaczyna się od zera:

    
    	public static void main(String[] args) {
    
       		int sundayIndex = DayOfWeek.SUNDAY.ordinal();
       		System.out.println(sundayIndex);
    }
    

    Wyjście:

    0
  • valueOf(): zwraca obiekt Enum, który odpowiada podanej nazwie:

    
    public static void main(String[] args) {
       DayOfWeek sunday = DayOfWeek.valueOf("SUNDAY");
       System.out.println(sunday);
    }
    

    Wyjście:

    DayOfWeek{tytuł = 'Niedziela'}
Uwaga: Do zdefiniowania pól Enum używamy wielkich liter. Są to stałe, dlatego używamy samych wielkich liter zamiast camelCase. Klasa Enum w Javie - 1
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION