JavaRush /Java-Blog /Random-DE /Aufzählung in Java. Praxisbeispiele. Konstruktoren und Me...

Aufzählung in Java. Praxisbeispiele. Konstruktoren und Methoden hinzufügen

Veröffentlicht in der Gruppe Random-DE
Hallo! Heute werden wir über einen speziellen Datentyp in Java sprechen – Enum(kurz für Enumeration). Was ist ihre Besonderheit? Stellen wir uns vor, dass wir Monate im Programm implementieren müssen. Aufzählung.  Praxisbeispiele.  Konstruktoren und Methoden hinzufügen - 1Es scheint, was ist das Problem? Sie müssen lediglich bestimmen, welche Eigenschaften ein Monat hat. Vielleicht brauchen wir zunächst den Namen des Monats und die Anzahl der Tage darin. Die Lösung des Problems sieht ganz einfach aus:

public class Month {

   private String name;
   private int daysCount;

   public Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getDaysCount() {
       return daysCount;
   }

   public void setDaysCount(int daysCount) {
       this.daysCount = daysCount;
   }

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
Komplettes Set bitte! Wir haben eine Klasse Month, die notwendigen Felder, Getter-Setter, toString(). Es sei denn, equals()Sie hashCode()müssen es hinzufügen, um vollkommen glücklich zu sein :) Allerdings haben wir ein konzeptionelles Problem. Wie Sie sich vielleicht erinnern, besteht einer der Hauptvorteile von OOP darin, dass es die Modellierung realer Entitäten erleichtert. Ein Stuhl, ein Auto, ein Planet – all diese Konzepte aus dem Alltag lassen sich durch Abstraktion leicht in einem Programm darstellen. Das Problem besteht darin, dass einige Entitäten in der realen Welt einen streng begrenzten Bedeutungsbereich haben. Es gibt nur 4 Jahreszeiten in einem Jahr. In der Musik gibt es nur 7 Noten. Der Kalender hat nur 12 Monate. Ocean hat nur 11 Freunde (obwohl das umstritten ist :)) Mit anderen Worten, eine reguläre Java-Klasse ist nicht in der Lage, diese Entitäten zu modellieren und ihre natürlichen Einschränkungen zu respektieren. Unsere Klasse Monthverfügt über alle notwendigen Felder. Aber wenn ein anderer Programmierer es verwendet, wird ihn niemand davon abhalten, völlig verrückte Objekte zu erstellen:

public class Main {

   Month month1 = new Month("lolkek", 322);
   Month month2 = new Month("yahoooooooooooo", 12345);

}
Wenn dies im Programm auftaucht, wird es nicht einfach sein, den Übeltäter zu finden! Einerseits hätte der Programmierer, der die Objekte erstellt hat, verstehen können, dass die Klasse Month„Monat des Jahres“ bedeutet, und keinen solchen Unsinn schreiben können. Andererseits nutzte er einfach die Möglichkeiten, die ihm der Klassendesigner bot. Kann ich beliebige Namen und Anzahl der Tage vergeben? Er hat es ernannt. Was tun in einer solchen Situation? Vor der Veröffentlichung der Java-Sprachversion 1.5 mussten Programmierer, ehrlich gesagt, aussteigen :) Damals erstellten sie folgende Konstrukte:

public class Month {

   private String name;
   private int daysCount;

   private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }

   public static Month JANUARY = new Month("Январь", 31);
   public static Month FEBRUARY = new Month("Февраль", 28);
   public static Month MARCH = new Month("Март", 31);

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
Hier haben wir die Anzahl der Monate auf drei statt zwölf vereinfacht, um das Beispiel kürzer zu halten. Solche Konstruktionen ermöglichten die Lösung des Problems. Die Optionen für erstellte Objekte wurden durch einen privaten Konstruktor eingeschränkt:

private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }
Programmierer, die die Klasse verwenden, konnten nicht einfach erstellen Month. Sie waren gezwungen, die endgültigen statischen Objekte zu verwenden, die vom Klassenentwickler bereitgestellt wurden. Es sah ungefähr so ​​aus:

public class Main {

   public static void main(String[] args) {

       Month january = Month.JANUARY;
       System.out.println(january);
   }

}
Java-Entwicklern ist jedoch ein bestehendes Problem aufgefallen. Natürlich ist es großartig, dass Programmierer mithilfe der in der Sprache verfügbaren Tools eine Lösung finden konnten, aber so einfach sieht es nicht aus! Es brauchte eine offensichtliche Lösung, die auch für Anfänger zugänglich ist. So erschien . in Java Enum. Im Wesentlichen Enumhandelt es sich um eine Java-Klasse, die eine begrenzte Menge an Wertobjekten bereitstellt. So sieht es aus:

public enum Month {
  
   JANUARY,
   FEBRUARY,
   MARCH
}
In der Definition haben wir angegeben, dass Enumes sich um eine Java-Klasse handelt, aber ist das wirklich so? Ja, und wir können es sogar überprüfen. Versuchen Sie zum Beispiel, unsere enum Monthvon einer anderen Klasse zu erben:

public abstract class AbstractMonth {
}

//ошибка! No extends clause allowed to enum
public enum Month extends AbstractMonth {

   JANUARY,
   FEBRUARY,
   MARCH
}
Warum passiert das? Wenn wir in ein Programm schreiben:

public enum Month
Der Compiler wandelt diesen Befehl in Code wie diesen um:

public Class Month extends Enum
Wie Sie bereits wissen, ist Mehrfachvererbung in Java nicht zulässig. Daher AbstractMonthkonnten wir nicht erben. Wie kann dieses neue Design Enumgenutzt werden? Und wie unterscheidet es sich vom alten Design mit static finalFeldern? Nun, das alte Design erlaubte uns beispielsweise nicht, unsere eigenen Werte in switch-Ausdrücken zu verwenden. Stellen Sie sich vor, wir möchten ein Programm erstellen, das uns daran erinnert, welche Feiertage diesen Monat gefeiert werden:

public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           //Fehler!
           case JANUARY:
       }
   }
}
Wie Sie sehen, gibt der Compiler hier einen Fehler aus. Aber nach dem Erscheinen von Java 1.5 enumwurde alles viel einfacher:

public enum Month {

   JANUARY,
   FEBRUARY,
   MARCH
}

public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {
          
           case JANUARY:
               System.out.println("7 января будет Рождество!");
               break;
           case FEBRUARY:
               System.out.println("В феврале празднуется День Защитника Отечества - 23 февраля!");
               break;
           case MARCH:
               System.out.println("В марте отмечается Всемирный Женский День - 8 марта!");
               break;
       }
   }
}



public class Main {

   public static void main(String[] args) {

       HolidayReminder reminder = new HolidayReminder();
       reminder.printHolidays(Month.JANUARY);

   }

}
Konsolenausgabe:

7 января будет Рождество!
Bitte beachten Sie: Der Zugriff auf Objekte Enumbleibt wie vor Java 1.5 statisch. Wir müssen kein Objekt erstellen, Monthum auf Monate zuzugreifen. Bei der Arbeit mit Aufzählungen ist es sehr wichtig, nicht zu vergessen, dass Enumes sich um eine vollwertige Klasse handelt. Das bedeutet, dass Sie bei Bedarf darin Konstruktoren und Methoden definieren können. Im vorherigen Codeteil haben wir beispielsweise einfach die Werte JANUAR, FEBRUAR, MÄRZ angegeben. Wir können unsere jedoch enum Monthso erweitern:

public enum Month {

   JANUARY("Январь", 31),
   FEBRUARY("Февраль", 28),
   MARCH("Март", 31),
   APRIL("Апрель", 30),
   MAY("Май", 31),
   JUNE("Июнь", 30),
   JULY("Июль", 31),
   AUGUST("Август", 31),
   SEPTEMBER("Сентябрь", 30),
   OCTOBER("Октябрь", 31),
   NOVEMBER("Ноябрь", 30),
   DECEMBER("Декабрь", 31);

   private String name;
   private int daysCount;

   Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }

   public static Month[] getWinterMonths() {

       return new Month[]{DECEMBER, JANUARY, FEBRUARY};
   }

   public static Month[] getSummerMonths() {

       return new Month[]{JUNE, JULY, AUGUST};
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getDaysCount() {
       return daysCount;
   }

   public void setDaysCount(int daysCount) {
       this.daysCount = daysCount;
   }

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
Hier haben wir 2 Felder zu unserem hinzugefügt enum– den Namen des Monats und die Anzahl der Tage, einen Konstruktor, der diese Felder verwendet, Getter-Setter, eine Methode toString()sowie 2 statische Methoden. Wie Sie sehen, gab es dabei keine Probleme: Wie bereits erwähnt, enumhandelt es sich um eine vollwertige Klasse:

import java.util.Arrays;

public class Main {

   public static void main(String[] args) {

       System.out.println(Arrays.toString(Month.getSummerMonths()));

   }

}
Konsolenausgabe:

[Month{name='Июнь', daysCount=30}, Month{name='Июль', daysCount=31}, Month{name='Август', daysCount=31}]
Abschließend möchte ich Ihnen ein äußerst nützliches Buch über Java empfehlen, nämlich „Effective Java“ von Joshua Bloch . Aufzählung.  Praxisbeispiele.  Konstruktoren und Methoden hinzufügen - 3Der Autor ist einer der Erfinder von Java, daher können Sie seinen Ratschlägen zum richtigen und kompetenten Einsatz von Sprachwerkzeugen auf jeden Fall vertrauen :) Im Zusammenhang mit unserem Vortrag rate ich Ihnen, dem Kapitel des Buches, das gewidmet ist, besondere Aufmerksamkeit zu schenken enum. Viel Spaß beim Lesen! :) :)
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION