CodeGym /Java-Blog /Random-DE /Aufzählung. Praxisbeispiele. Konstruktoren und Methoden h...
Autor
Alex Vypirailenko
Java Developer at Toshiba Global Commerce Solutions

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

Veröffentlicht in der Gruppe Random-DE
Hallo! Heute sprechen wir über einen der speziellen Datentypen von Java: Enum(kurz für „Enumeration“). Was macht es besonders? Stellen wir uns vor, was wir brauchen, um „Monate“ in einem Programm zu implementieren. Aufzählung.  Praxisbeispiele.  Konstruktoren und Methoden hinzufügen - 1 Scheint doch nicht problematisch zu sein, oder? Wir müssen nur bestimmen, welche Eigenschaften dieser Monat hat. Vielleicht brauchen wir zuerst den Namen des Monats und die Anzahl der Tage darin. Die Lösung sieht ziemlich 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 +
               '}';
   }
}
Der ganze Shabang! Wir haben eine MonthKlasse, die erforderlichen Felder, Getter/Setter und toString(). Es sei denn natürlich, wir müssen equals()und hinzufügenhashCode()um vollkommenes Glück zu erreichen :) Aber hier haben wir ein konzeptionelles Problem. Wie Sie sich wahrscheinlich erinnern, besteht einer der Hauptvorteile von OOP darin, dass es die Modellierung von Entitäten aus der realen Welt erleichtert. Ein Stuhl, ein Auto, ein Planet – all diese Konzepte aus dem alltäglichen Leben lassen sich mit Hilfe der Abstraktion leicht in einem Programm darstellen. Das Problem besteht darin, dass einige reale Entitäten einen streng begrenzten Wertebereich haben. Es gibt nur 4 Jahreszeiten in einem Jahr. Es gibt nur 8 Noten in einer Oktave. Der Kalender hat nur 12 Monate. Und Danny Ocean von Ocean's 11 hat nur 11 Freunde (obwohl das keine Rolle spielt :)) Was wichtig ist, ist, dass eine gewöhnliche Java-Klasse nicht in der Lage ist, diese Entitäten zu modellieren und ihre natürlichen Einschränkungen durchzusetzen. UnserMonthDie Klasse verfügt über alle erforderlichen Felder. Aber wenn ein anderer Programmierer es verwendet, kann 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 in unserem Code vorkommt, wird es nicht einfach sein, den Übeltäter zu finden! Einerseits könnte der Programmierer, der die Objekte erstellt, erkennen, dass die MonthKlasse „Monat im Jahr“ bedeutet, und solchen Unsinn nicht schreiben. Andererseits nutzt der Programmierer nur die Fähigkeiten aus, die der Klassendesigner bereitgestellt hat. Ist es möglich, beliebige Namen und Anzahlen von Tagen zu vergeben? Genau das haben wir. Was sollen wir dann in dieser Situation tun? Ehrlich gesagt mussten Programmierer vor der Veröffentlichung von Java 1.5 kreativ werden :) Damals erstellten sie Strukturen wie diese:

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("January", 31);
   public static Month FEBRUARY = new Month("February", 28);
   public static Month MARCH = new Month("March", 31);

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
Hier haben wir die Anzahl der Monate von zwölf auf drei gekürzt, um das Beispiel kürzer zu machen. Solche Konstruktionen ermöglichten die Lösung des Problems. Die Möglichkeit, Objekte zu erstellen, war auf einen privaten Konstruktor beschränkt:

private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }
Programmierer, die die Klasse verwenden, konnten nicht einfach MonthObjekte erstellen. Sie mussten die vom Klassenentwickler bereitgestellten endgültigen statischen Objekte verwenden. Zum Beispiel so:

public class Main {

   public static void main(String[] args) {

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

}
Doch Java-Entwickler machten auf das bestehende Problem aufmerksam. Natürlich ist es großartig, dass Programmierer mithilfe der in der Sprache verfügbaren Tools eine Lösung finden konnten, aber es sieht nicht ganz einfach aus! Es musste eine offensichtliche Lösung gefunden werden, auch für Anfänger. Und so Enumerschien es in Java. Im Grunde Enumhandelt es sich um eine Java-Klasse, die einen begrenzten Satz von Objektwerten bereitstellt. So sieht es aus:

public enum Month {
  
   JANUARY,
   FEBRUARY,
   MARCH
}
In der Definition haben wir angegeben, dass es Enumsich um eine Java-Klasse handelt, aber stimmt das wirklich? Ja, und wir können es sogar überprüfen. Versuchen Sie beispielsweise, unsere MonthEnumeration dazu zu bringen, eine andere Klasse zu erben:

public abstract class AbstractMonth {
}

// Error! The extends clause cannot be used with an enum
public enum Month extends AbstractMonth {

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

public enum Month
Der Compiler wandelt diese Anweisung in den folgenden Code um:

public Class Month extends Enum
Wie Sie bereits wissen, unterstützt Java keine Mehrfachvererbung. Daher können wir nicht erben AbstractMonth. Wie kann dieses neue Konstrukt Enumverwendet werden? Und wie unterscheidet es sich vom alten Konstrukt mit static finalFeldern? Nun, zum Beispiel erlaubte uns das alte Konstrukt nicht, unsere eigenen Werte in switchAnweisungen zu verwenden. Stellen Sie sich vor, wir möchten ein Programm erstellen, das uns an die Feiertage erinnert, die jeden Monat gefeiert werden:

public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           // Error!
           case JANUARY:
       }
   }
}
Wie Sie sehen, gibt der Compiler hier einen Fehler aus. Aber sobald enumes in Java 1.5 erschien, wurde alles viel einfacher:

public enum Month {

   JANUARY,
   FEBRUARY,
   MARCH
}

public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {
          
           case JANUARY:
               System.out.println("New Year's Day is January 1st!");
               break;
           case FEBRUARY:
               System.out.println("Valentine's Day is February 14th!");
               break;
           case MARCH:
               System.out.println("Saint Patrick's Day is March 17th!");
               break;
       }
   }
}


public class Main {

   public static void main(String[] args) {

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

   }

}
Konsolenausgabe:

New Year's Day is January 1st!
Beachten Sie, dass der Zugriff auf EnumObjekte statisch blieb, genau wie vor Java 1.5. Wir müssen kein Objekt erstellen, Monthum auf die Monate zuzugreifen. Bei der Arbeit mit Aufzählungen ist es sehr wichtig, nicht zu vergessen, dass es Enumsich um eine vollwertige Klasse handelt. Das bedeutet, dass Sie bei Bedarf darin Konstruktoren und Methoden definieren können. Im vorherigen Codefragment haben wir beispielsweise einfach die Werte angegeben: JANUAR, FEBRUAR, MÄRZ. Wir können unsere Enumeration jedoch Monthwie folgt erweitern:

public enum Month {

   JANUARY("January", 31),
   FEBRUARY("February", 28),
   MARCH("March", 31),
   APRIL("April", 30),
   MAY("May", 31),
   JUNE("June", 30),
   JULY("July", 31),
   AUGUST("August", 31),
   SEPTEMBER("September", 30),
   OCTOBER("October", 31),
   NOVEMBER("November", 30),
   DECEMBER("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 unsere enum2 Felder (den Namen des Monats und die Anzahl der Tage), einen Konstruktor, der diese Felder verwendet, Getter/Setter, die toString()Methode und 2 statische Methoden angegeben. Wie Sie sehen, gab es dabei keine Probleme. Auch hier Enumhandelt es sich wirklich 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='June', daysCount=30}, Month{name='July', daysCount=31}, Month{name='August', daysCount=31}]
Abschließend möchte ich ein äußerst nützliches Java-Buch empfehlen, nämlich „Effective Java“ von Joshua Bloch . Aufzählung.  Praxisbeispiele.  Konstruktoren und Methoden hinzufügen - 3Der Autor ist einer der Schöpfer von Java, daher können Sie sich auf jeden Fall auf seine Ratschläge zum richtigen und kompetenten Einsatz der Sprachwerkzeuge verlassen :) Im Hinblick auf unsere Lektion empfehle ich Ihnen, dem Kapitel des Buches besondere Aufmerksamkeit zu schenken Enum. Fröhliches Lesen! :) :)
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION