Enums in Java erweitern
Dieses Tutorial zeigt, wie man die enum
-Funktionalität in Java erweitert.
Erweitern Sie enum
in Java
Wir können enum
als eine Art Compiler-Magie betrachten, denn im byte
-Code wird das enum
als Klasse mit mehreren statischen
Membern dargestellt und vom abstrakten java.lang.Enum
geerbt.
Aus diesem Grund kann das enum
keine andere Klasse oder enum
erweitern. Da wir enum
in Java nicht erweitern können, ist es auch für keine Klasse möglich, ein enum
zu erweitern. Lassen Sie uns anhand des folgenden Beispielcodes lernen und sehen, was passiert.
Beispielcode:
package delftstack;
enum Cars { Audi, BMW, Marcedes }
public class Example extends Cars {
public static void main(String... args) {}
}
Der obige Code hat ein enum
namens Cars
, und die Klasse Example
versucht, es zu erweitern. Siehe Ausgabe:
/Example.java:5: error: cannot inherit from final Cars
public class Example extends Cars {
^
/Example.java:5: error: enum types are not extensible
public class Example extends Cars {
^
2 errors
Wie wir sehen können, kann die Klasse das enum
nicht erweitern. Wenn es also unmöglich ist, das enum
zu erweitern, können wir seine Funktionalität trotzdem erweitern?
Die Funktionalität kann als implementierte Methode im enum
definiert werden. Zum Beispiel kann das enum
Cars
aus dem obigen Code abstrakte Methoden für jedes Member deklarieren; siehe Beispiel:
enum Cars {
Audi {
@Override
public void drive() {}
},
BMW {
@Override
public void drive() {}
},
Mercedes {
@Override
public void drive() {}
},
;
public abstract void drive();
}
Wie wir sehen können, kann jedes Mitglied die Methode drive()
überschreiben. Aber leider ist es nicht immer möglich, Methoden in enum
zu erstellen, weil:
- Wenn das
enum
zu einer Bibliothek eines Drittanbieters oder einem anderen Team gehört, erlaubt es keine Implementierung abstrakter Methoden. - Wenn es zu dem Modul gehört, das nicht die für die Methode
drive()
erforderliche Abhängigkeit hat. - Wenn das
enum
mit anderen Funktionen und Daten überladen ist, wird es unlesbar.
Es werden einige Lösungen bereitgestellt, die diese Probleme lösen und die Funktionalität von enum
in Java erweitern können.
Lösung 1: Mirror enum
in Java
Wie der Name schon sagt, müssen wir ein weiteres enum
mit denselben Daten erstellen. Dieses neue enum
wird auch die drive()
-Methode implementieren, also haben wir jetzt zwei enums:
Beispielcode für enum Cars
:
enum Cars {
Audi {
@Override
public void drive() {}
},
BMW {
@Override
public void drive() {}
},
Mercedes {
@Override
public void drive() {}
},
;
public abstract void drive();
}
Beispielcode für enum DriveCars
:
enum DriveCars {
Audi {
@Override
public void drive() {}
},
BMW {
@Override
public void drive() {}
},
Mercedes {
@Override
public void drive() {}
},
;
public abstract void drive();
}
Das zweite enum
ist der Spiegel des ersten. Jetzt können wir diese beiden Aufzählungen verwenden, indem wir die Funktionalität erweitern; wir müssen eingebaute enum
-Methoden verwenden, nämlich name()
und valueof()
.
Sehen Sie sich das folgende Beispiel zur Verwendung an:
Cars cars = ... DriveCars.valueOf(cars.name()).drive();
Der obige Code zeigt, wie die enum Cars
-Funktionalität in den enum DriveCars
verwendet wird. Das heißt, die Funktionalität wird erweitert.
Die Methode name()
im obigen Code ist final
, was nicht überschrieben werden kann, und die Methode valueOf
wird vom Compiler generiert. Beide Verfahren passen gut zusammen, wenn im erweiterten Betrieb kein Funktionsfehler auftritt.
Es gibt ein Problem mit dem obigen Code, wenn enum Cars
geändert wird, hat das enum DriveCars
keine Ahnung, und es führt zum Scheitern des name
- und valueof
-Tricks. Um dieses Problem zu lösen, müssen wir DriveCars
mitteilen, dass sein Elternspiegel Cars
ist.
Dafür können wir einen statischen
Initialisierer verwenden, um DriveCars
und Cars
zu vergleichen, der die Ausnahme auslöst, wenn beide Aufzählungen nicht übereinstimmen. Hier ist ein Beispiel dafür aus der enumus-Bibliothek:
enum DriveCars {
....static { Mirror.of(Cars.class); }
}
Die Utility-Klasse prüft, ob beide Aufzählungen übereinstimmen oder nicht. Diese Methode validiert den name()
- und valueOf()
-Trick.
Lösung 2: Map enum
in Java
Wenn Sie kein weiteres enum
erstellen möchten, das nur eine Methode enthält. In diesem Fall können wir statt enum
interface
verwenden; siehe das Beispiel unten:
public interface Driver {
void drive();
}
Um nun diese Schnittstelle Drive
mit den enum Cars
zu verwenden, können wir eine Zuordnung zwischen ihnen erstellen. Hier ist das Beispiel für die Karte:
Map<Cars, Driver> drivers = new EnumMap<>(Cars.class) {
{
put(Audi, new Driver() {
@Override
public void driver() {}
}) put(BMW, new Driver() {
@Override
public void driver() {}
}) put(Mercedes, new Driver() {
@Override
public void driver() {}
})
}
}
Um sie jetzt zu verwenden, verwenden Sie diesen einfachen Code:
drivers.get(Cars).drive();
Die im obigen Code verwendete EnumMap
garantiert, dass jedes enum
-Mitglied nur einmal auftaucht, garantiert aber keinen Eintrag für jedes Mitglied.
Wir können überprüfen, ob die Größe der Karte der Anzahl der Mitglieder von Aufzählungen entspricht:
drivers.size() == Cars.values().length
Auch für diesen Fall bietet die Bibliothek enumus ein Hilfsmittel: Passt die Karte nicht zu den Cars
, wirft sie die IllegalStateException
. Hier ist das Dienstprogramm:
EnumMapValidator.validateValues(Cars.class, map, "Cars map");
Beide obigen Methoden zeigen, wie Sie Aufzählungen durch Erweitern ihrer Funktionalität leistungsfähig machen können. Obwohl es unmöglich ist, ein enum
direkt zu erweitern, können wir diese Tricks verwenden, um ihre Funktionalitäten zu erweitern.
Sheeraz is a Doctorate fellow in Computer Science at Northwestern Polytechnical University, Xian, China. He has 7 years of Software Development experience in AI, Web, Database, and Desktop technologies. He writes tutorials in Java, PHP, Python, GoLang, R, etc., to help beginners learn the field of Computer Science.
LinkedIn Facebook