Anhängen von Werten an Java Enum

1. Einleitung

Der Java- Aufzählungstyp bietet eine sprachunterstützte Möglichkeit zum Erstellen und Verwenden konstanter Werte. Durch die Definition einer endlichen Menge von Werten ist die Aufzählung typsicherer als konstante Literalvariablen wie String oder int .

Allerdings Enum sind Werte erforderlich gültige Bezeichner sein , und wir sind ermutigt SCREAMING_SNAKE_CASE vereinbarungsgemäß zu verwenden.

Angesichts dieser Einschränkungen ist der Enum- Wert allein nicht für von Menschen lesbare Zeichenfolgen oder Nicht-Zeichenfolgenwerte geeignet .

In diesem Tutorial verwenden wir die Funktionen der Enumeration als Java-Klasse, um die gewünschten Werte anzuhängen.

2. Verwenden von Java Enum als Klasse

Wir erstellen oft eine Aufzählung als einfache Liste von Werten. Hier sind zum Beispiel die ersten beiden Zeilen des Periodensystems als einfache Aufzählung :

public enum Element { H, HE, LI, BE, B, C, N, O, F, NE }

Mit der Syntax oben, haben wir zehn statische, letzte Instanzen des erzeugten ENUM namens Element . Dies ist zwar sehr effizient, wir haben jedoch nur die Elementsymbole erfasst. Und während die Großbuchstabenform für Java-Konstanten geeignet ist, schreiben wir die Symbole normalerweise nicht so.

Darüber hinaus fehlen uns auch andere Eigenschaften der Periodensystemelemente wie Name und Atomgewicht.

Obwohl der Aufzählungstyp in Java ein spezielles Verhalten aufweist, können wir wie bei anderen Klassen Konstruktoren, Felder und Methoden hinzufügen. Aus diesem Grund können wir unsere Aufzählung erweitern , um die Werte aufzunehmen, die wir benötigen.

3. Hinzufügen eines Konstruktors und eines letzten Feldes

Beginnen wir mit dem Hinzufügen der Elementnamen. Wir werden die Namen mit einem Konstruktor in eine endgültige Variable setzen :

public enum Element { H("Hydrogen"), HE("Helium"), // ... NE("Neon"); public final String label; private Element(String label) { this.label = label; } }

Zunächst bemerken wir die spezielle Syntax in der Deklarationsliste. Auf diese Weise wird ein Konstruktor für Aufzählungstypen aufgerufen . Obwohl es illegal ist, den neuen Operator für eine Aufzählung zu verwenden , können wir Konstruktorargumente in der Deklarationsliste übergeben.

Wir erklären dann eine Instanz Variable Label . Es gibt ein paar Dinge zu beachten.

Zuerst haben wir die Etikettenkennung anstelle des Namens gewählt . Obwohl der Name des Mitgliedsfelds zur Verwendung verfügbar ist, wählen wir die Bezeichnung , um Verwechslungen mit der vordefinierten Methode Enum.name () zu vermeiden .

Zweitens unser Label ist Feld endgültig . Während Felder einer Aufzählung nicht endgültig sein müssen , möchten wir in den meisten Fällen nicht, dass sich unsere Beschriftungen ändern. Im Sinne einer konstanten Aufzählung ist dies sinnvoll.

Schließlich ist das Beschriftungsfeld öffentlich. Daher können wir direkt auf das Etikett zugreifen:

System.out.println(BE.label);

Andererseits kann das Feld privat sein und mit einer getLabel () -Methode aufgerufen werden. Der Kürze halber wird in diesem Artikel weiterhin der öffentliche Feldstil verwendet.

4. Suchen von Java Enum- Werten

Java bietet eine valueOf (String) -Methode für alle Aufzählungstypen . Somit können wir immer einen Aufzählungswert erhalten , der auf dem deklarierten Namen basiert:

assertSame(Element.LI, Element.valueOf("LI"));

Möglicherweise möchten wir jedoch auch einen Aufzählungswert in unserem Beschriftungsfeld nachschlagen . Dazu können wir eine statische Methode hinzufügen :

public static Element valueOfLabel(String label) { for (Element e : values()) { if (e.label.equals(label)) { return e; } } return null; }

Die statische valueOfLabel () Methode iteriert die Elementwerte , bis sie eine Übereinstimmung findet. Es wird null zurückgegeben, wenn keine Übereinstimmung gefunden wird. Umgekehrt könnte eine Ausnahme ausgelöst werden, anstatt null zurückzugeben .

Sehen wir uns ein kurzes Beispiel mit unserer valueOfLabel () -Methode an:

assertSame(Element.LI, Element.valueOfLabel("Lithium"));

5. Zwischenspeichern der Suchwerte

Wir können das Iterieren der Aufzählungswerte vermeiden , indem wir eine Map verwenden, um die Beschriftungen zwischenzuspeichern . Dazu definieren wir eine statische endgültige Map und füllen sie beim Laden der Klasse:

public enum Element { // ... enum values private static final Map BY_LABEL = new HashMap(); static { for (Element e: values()) { BY_LABEL.put(e.label, e); } } // ... fields, constructor, methods public static Element valueOfLabel(String label) { return BY_LABEL.get(label); } }

Durch das Zwischenspeichern werden die Aufzählungswerte nur einmal wiederholt , und die Methode valueOfLabel () wird vereinfacht.

Alternativ können wir den Cache beim ersten Zugriff in der valueOfLabel () -Methode träge erstellen . In diesem Fall muss der Kartenzugriff synchronisiert werden, um Parallelitätsprobleme zu vermeiden.

6. Mehrere Werte anhängen

Der Enum- Konstruktor kann mehrere Werte akzeptieren . Zur Veranschaulichung fügen wir die Ordnungszahl als int und das Atomgewicht als float hinzu :

public enum Element { H("Hydrogen", 1, 1.008f), HE("Helium", 2, 4.0026f), // ... NE("Neon", 10, 20.180f); private static final Map BY_LABEL = new HashMap(); private static final Map BY_ATOMIC_NUMBER = new HashMap(); private static final Map BY_ATOMIC_WEIGHT = new HashMap(); static { for (Element e : values()) { BY_LABEL.put(e.label, e); BY_ATOMIC_NUMBER.put(e.atomicNumber, e); BY_ATOMIC_WEIGHT.put(e.atomicWeight, e); } } public final String label; public final int atomicNumber; public final float atomicWeight; private Element(String label, int atomicNumber, float atomicWeight) { this.label = label; this.atomicNumber = atomicNumber; this.atomicWeight = atomicWeight; } public static Element valueOfLabel(String label) { return BY_LABEL.get(label); } public static Element valueOfAtomicNumber(int number) { return BY_ATOMIC_NUMBER.get(number); } public static Element valueOfAtomicWeight(float weight) { return BY_ATOMIC_WEIGHT.get(weight); } }

In ähnlicher Weise können wir der Aufzählung beliebige Werte hinzufügen , z. B. die richtigen Groß- und Kleinschreibung, z. B. "He", "Li" und "Be".

Darüber hinaus können wir unserer Aufzählung berechnete Werte hinzufügen, indem wir Methoden zum Ausführen von Operationen hinzufügen.

7. Steuerung der Schnittstelle

As a result of adding fields and methods to our enum, we've changed its public interface. Therefore, our code, which uses the core Enumname() and valueOf() methods, will be unaware of our new fields.

The staticvalueOf() method is already defined for us by the Java language. Therefore, we can't provide our own valueOf() implementation.

Similarly, because the Enum.name() method is final, we can't override it either.

As a result, there's no practical way to utilize our extra fields using the standard Enum API. Instead, let's look at some different ways to expose our fields.

7.1. Overriding toString()

Overriding toString() may be an alternative to overriding name():

@Override public String toString() { return this.label; }

By default, Enum.toString() returns the same value as Enum.name().

7.2. Implementing an Interface

The enum type in Java can implement interfaces. While this approach is not as generic as the Enum API, interfaces do help us generalize.

Let's consider this interface:

public interface Labeled { String label(); }

For consistency with the Enum.name() method, our label() method does not have a get prefix.

And, because the valueOfLabel() method is static, we do not include it in our interface.

Schließlich können wir die Schnittstelle in unserer Aufzählung implementieren :

public enum Element implements Labeled { // ... @Override public String label() { return label; } // ... }

Ein Vorteil dieses Ansatzes besteht darin, dass die beschriftete Schnittstelle auf jede Klasse angewendet werden kann, nicht nur auf Aufzählungstypen . Anstatt sich auf die generische Enum- API zu verlassen, haben wir jetzt eine kontextspezifischere API.

8. Fazit

In diesem Artikel haben wir viele Funktionen der Java Enum- Implementierung untersucht. Durch Hinzufügen von Konstruktoren, Feldern und Methoden können wir feststellen, dass die Aufzählung viel mehr kann als nur wörtliche Konstanten.

Wie immer finden Sie den vollständigen Quellcode für diesen Artikel auf GitHub.