Menu

Java-Enums: eine feste Menge benannter Konstanten

Was ein Java-Enum ist, wie man eines deklariert, Felder und Methoden hinzufügt, darüber per switch verzweigt und warum ein Enum besser ist als ein Haufen int- oder String-Konstanten.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Eine feste Menge benannter Werte

Manche Werte ergeben nur als Element einer kleinen, bekannten Liste Sinn: die Wochentage, die Farben in einem Kartenspiel, die Zustände, in denen eine Bestellung sein kann. Du könntest sie mit int-Codes (0 für ausstehend, 1 für versandt) oder Zeichenketten ("PENDING", "SHIPPED") modellieren, aber nichts hindert einen Aufrufer daran, 7 oder "PNEDING" zu übergeben. Ein enum schließt diese Lücke – der Typ selbst lässt nur die Werte zu, die du deklariert hast.

Day ist ein brandneuer Typ. Eine Variable vom Typ Day kann genau eine dieser sieben Konstanten enthalten – oder null – und nichts anderes. Der Compiler weist Day d = "WEDNESDAY"; oder Day d = 2; zurück. Genau diese Garantie ist der ganze Sinn.

Jede Konstante (Day.MONDAY usw.) ist eine einzelne, gemeinsam genutzte Instanz, die einmal erstellt wird. Da es immer nur ein MONDAY gibt, vergleichst du Enums mit == statt mit equals – sie sind dasselbe Objekt.

switch über ein Enum

Enums passen von Natur aus zu switch. Innerhalb des switch musst du nicht einmal jede Konstante mit dem Typnamen qualifizieren:

Schreibe innerhalb des switch case SATURDAY, nicht case Day.SATURDAY – Java leitet den Typ ab. Der große Vorteil gegenüber einem switch über eine Zeichenkette oder einen int ist: Wenn du später eine neue Konstante hinzufügst, können deine IDE und die Vollständigkeitsprüfungen jeden switch markieren, der vergessen hat, sie zu behandeln.

Über alle Konstanten iterieren

Jedes Enum erhält automatisch eine statische values()-Methode, die alle seine Konstanten in Deklarationsreihenfolge zurückgibt, sowie ein ordinal(), das jeder Konstante ihre nullbasierte Position gibt:

name() liefert den Bezeichner der Konstante als String, und values() eignet sich perfekt, um Menüs aufzubauen oder über Optionen zu iterieren. Eine Warnung: Speichere ordinal() nirgendwo dauerhaft. Wenn jemand die Konstanten später umsortiert, verschieben sich die Zahlen und deine gespeicherten Daten gehen kaputt. Behandle ordinal() als Implementierungsdetail, nicht als stabilen Identifikator.

Enums sind echte Klassen: Felder und Methoden

Hier gehen Java-Enums über die Enums mit benannten Ganzzahlen anderer Sprachen hinaus. Jede Konstante kann Daten tragen, die über einen Konstruktor übergeben werden, und das Enum kann Methoden haben. Du listest zuerst die Konstanten auf, gibst jeder ihre Konstruktorargumente und deklarierst dann nach einem Semikolon die Felder, den Konstruktor und die Methoden.

Beachte die Struktur: Die Konstanten kommen zuerst und enden mit einem Semikolon, danach folgt der Rest der Klasse. Der Konstruktor ist implizit private – du kannst niemals new Planet(...) schreiben, denn die einzigen erlaubten Instanzen sind die oben deklarierten. Die final-Felder machen jede Konstante unveränderlich, was genau das ist, was man für gemeinsam genutzte Singletons will.

Von einer Zeichenkette und zurück

Um eine Zeichenkette in die passende Konstante umzuwandeln, verwende das automatisch erzeugte valueOf:

valueOf gleicht den Konstantennamen exakt ab, einschließlich Groß-/Kleinschreibung, und wirft IllegalArgumentException, wenn es keine Übereinstimmung gibt. Das ist der häufige Fallstrick: "shipped" passt nicht zu SHIPPED. Wenn du Benutzereingaben oder externe Daten verarbeitest, normalisiere zuerst die Schreibweise (input.toUpperCase()) und umschließe den Aufruf mit einem try/catch, sonst stürzt du beim ersten ungültigen Wert ab.

Verhalten pro Konstante

Manchmal muss jede Konstante sich unterschiedlich verhalten, nicht nur unterschiedliche Daten halten. Du kannst einem Enum eine abstrakte Methode geben und jede Konstante in einem kleinen Rumpf ihre eigene Implementierung liefern lassen:

Das wird manchmal das Muster der „konstantenspezifischen Methode" genannt. Es ersetzt einen ausufernden switch über die Konstante durch Verhalten, das direkt an jede einzelne angehängt ist – füge eine neue Operation hinzu, und der Compiler zwingt dich, ihr apply zu definieren, sodass du keinen Fall vergessen kannst.

Wann man zu einem Enum greift

Verwende ein Enum immer dann, wenn ein Wert von Natur aus zu einer kleinen, festen, zur Compilezeit bekannten Menge gehört:

  • Zustände in einem Workflow (PENDING, SHIPPED, DELIVERED).
  • Kategorien, Modi oder Typen (READ, WRITE, EXECUTE).
  • Überall dort, wo du versucht warst, ein Bündel von public static final int-Konstanten zu definieren – das Enum gibt dir dieselben benannten Werte plus Typsicherheit, ein lesbares toString und switch-Unterstützung gratis dazu.

Verwende kein Enum für eine offene oder zur Laufzeit bestimmte Menge (Benutzernamen, eine aus einer Datenbank geladene Länderliste). Enums sind zur Compilezeit fest verdrahtet; wenn sich die Menge ändert, während das Programm läuft, willst du stattdessen eine gewöhnliche Collection.

Als Nächstes: Generics

Du hast nun gesehen, wie values() ein Planet[] zurückgibt, und auf früheren Seiten die Verwendung von List<Shape> – diese <...>-Syntax sind Generics, Javas Art, eine einzige Klasse oder Methode zu schreiben, die für viele Typen funktioniert und dabei volle Typsicherheit bewahrt. Als Nächstes nehmen wir uns vor, wie List<String> und Map<K, V> tatsächlich funktionieren und wie du deine eigenen generischen Typen schreibst.

Häufig gestellte Fragen

Was ist ein Enum in Java?

Ein enum ist ein spezieller Typ, dessen Wert nur einer aus einer festen, benannten Menge von Konstanten sein kann – etwa Day.MONDAY oder Status.ACTIVE. Jede Konstante ist eine einzelne, vorab erstellte Instanz des Enums. Enums geben dir Typsicherheit: Eine Methode, die ein Day entgegennimmt, kann nur einen echten Tag erhalten, niemals eine vertippte Zeichenkette oder einen int außerhalb des Bereichs.

Kann ein Java-Enum Felder und Methoden haben?

Ja. Ein Enum ist eine vollwertige Klasse. Du kannst jeder Konstante Konstruktorargumente übergeben, sie in private final-Feldern speichern und Methoden hinzufügen, die sie verwenden. Zum Beispiel übergibt MERCURY(3.3e23, 2.4e6) Masse und Radius an den Konstruktor des Enums, und eine surfaceGravity()-Methode kann daraus einen Wert berechnen.

Was ist der Unterschied zwischen values() und valueOf() bei einem Java-Enum?

values() liefert ein Array aller Konstanten des Enums in Deklarationsreihenfolge – praktisch, um über jede Option zu iterieren. valueOf("NAME") macht das Gegenteil: Es sucht die Konstante, deren Name exakt mit der Zeichenkette übereinstimmt, und wirft IllegalArgumentException, wenn keine passt. Beide werden vom Compiler automatisch erzeugt.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S