Effizientes Verwalten von Konstanten mit Java Enums
Enum wurde in Java 1.5 als neuer Typ eingeführt, dessen Felder aus einer festen Menge von Konstanten bestehen. Zum Beispiel können wir Richtungen als Java Enum mit den festen Feldern EAST, WEST, NORTH und SOUTH erstellen.
Java Enum
In diesem Tutorial lernen wir, wie man ein Enum erstellt. Wir werden uns auch die Vorteile von Enums in Java und die Eigenschaften von Enum-Typen ansehen. Außerdem lernen wir die Verwendung von Java Enum valueOf, enum values, EnumSet und EnumMap anhand von Beispielen.
Java Enum Beispiel
Das Java-Schlüsselwort enum
wird verwendet, um einen Enum-Typ zu erstellen. Schauen wir uns das folgende Java Enum-Beispielprogramm an.
package com.journaldev.enums;
public enum ThreadStates {
START,
RUNNING,
WAITING,
DEAD;
}
Im obigen Beispiel ist ThreadStates das Enum mit den festen Konstantenfeldern START, RUNNING, WAITING und DEAD.
Java Enum vs Konstanten
Nun sehen wir uns an, warum Java Enums besser als normale Konstantenfelder in Java-Klassen sind. Erstellen wir eine ähnliche Konstantenklasse in Java.
package com.journaldev.enums;
public class ThreadStatesConstant {
public static final int START = 1;
public static final int WAITING = 2;
public static final int RUNNING = 3;
public static final int DEAD = 4;
}
Nun sehen wir, wie sowohl Enum als auch Konstanten in einem Java-Programm verwendet werden:
/**
* Diese Methode zeigt den Vorteil der Verwendung von Enum gegenüber Konstanten
*/
private static void benefitsOfEnumOverConstants() {
//Enum-Werte sind festgelegt
simpleEnumExample(ThreadStates.START);
simpleEnumExample(ThreadStates.WAITING);
simpleEnumExample(ThreadStates.RUNNING);
simpleEnumExample(ThreadStates.DEAD);
simpleEnumExample(null);
simpleConstantsExample(1);
simpleConstantsExample(2);
simpleConstantsExample(3);
simpleConstantsExample(4);
//wir können jede int-Konstante übergeben
simpleConstantsExample(5);
}
private static void simpleEnumExample(ThreadStates th) {
if(th == ThreadStates.START) System.out.println("Thread gestartet");
else if (th == ThreadStates.WAITING) System.out.println("Thread wartet");
else if (th == ThreadStates.RUNNING) System.out.println("Thread läuft");
else System.out.println("Thread ist tot");
}
private static void simpleConstantsExample(int i) {
if(i == ThreadStatesConstant.START) System.out.println("Thread gestartet");
else if (i == ThreadStatesConstant.WAITING) System.out.println("Thread wartet");
else if (i == ThreadStatesConstant.RUNNING) System.out.println("Thread läuft");
else System.out.println("Thread ist tot");
}
Wenn wir uns das obige Beispiel ansehen, haben wir zwei Risiken bei der Verwendung von Konstanten, die durch das Enum gelöst werden.
- Wir können jede int-Konstante an die Methode
simpleConstantsExample
übergeben, aber wir können nur feste Werte ansimpleEnumExample
übergeben, was Typensicherheit bietet. - Wir können den int-Konstantenwert in der Klasse
ThreadStatesConstant
ändern, aber das obige Programm wird keine Ausnahme auslösen. Unser Programm funktioniert möglicherweise nicht wie erwartet, aber wenn wir die Enum-Konstanten ändern, erhalten wir einen Compiler-Fehler, der jegliche Möglichkeit von Laufzeitproblemen ausschließt.
Java Enum Methoden
Nun sehen wir uns weitere Funktionen von Java Enum anhand eines Beispiels an.
package com.journaldev.enums;
import java.io.Closeable;
import java.io.IOException;
/**
* Dieses Enum-Beispiel zeigt alle Dinge, die wir mit Enum-Typen machen können
*
*/
public enum ThreadStatesEnum implements Closeable {
START(1) {
@Override
public String toString() {
return "START-Implementierung. Priorität=" + getPriority();
}
@Override
public String getDetail() {
return "START";
}
},
RUNNING(2) {
@Override
public String getDetail() {
return "RUNNING";
}
},
WAITING(3) {
@Override
public String getDetail() {
return "WAITING";
}
},
DEAD(4) {
@Override
public String getDetail() {
return "DEAD";
}
};
private int priority;
public abstract String getDetail();
// Enum-Konstruktoren sollten immer privat sein.
private ThreadStatesEnum(int i) {
priority = i;
}
// Enum kann Methoden haben
public int getPriority() {
return this.priority;
}
public void setPriority(int p) {
this.priority = p;
}
// Enum kann Funktionen überschreiben
@Override
public String toString() {
return "Standard-Implementierung von ThreadStatesConstructors. Priorität=" + getPriority();
}
@Override
public void close() throws IOException {
System.out.println("Schließen von Enum");
}
}
Java Enum Wichtige Punkte
Hier sind einige wichtige Punkte für Enums in Java.
- Alle Java-Enums erweitern implizit die Klasse
java.lang.Enum
, die die KlasseObject
erweitert und die SchnittstellenSerializable
undComparable
implementiert. Daher können wir keine Klasse in einem Enum erweitern. - Da
enum
ein Schlüsselwort ist, können wir den Paketnamen nicht mit ihm beenden, z.B. istcom.journaldev.enum
kein gültiger Paketname. - Enum kann Schnittstellen implementieren. Wie im obigen Enum-Beispiel implementiert es die Schnittstelle
Closeable
. - Enum-Konstruktoren sind immer privat.
- Wir können keine Instanz von Enum mit dem Operator
new
erstellen. - Wir können abstrakte Methoden in Java Enum deklarieren, dann müssen alle Enum-Felder die abstrakte Methode implementieren. Im obigen Beispiel ist
getDetail()
die abstrakte Methode und alle Enum-Felder haben sie implementiert. - Wir können eine Methode in Enum definieren, und Enum-Felder können sie ebenfalls überschreiben. Zum Beispiel ist die Methode
toString()
in Enum definiert und das Enum-FeldSTART
hat sie überschrieben. - Java Enum-Felder haben einen Namensraum, wir können Enum-Felder nur mit dem Klassennamen verwenden, wie
ThreadStates.START
. - Enums können in
switch
-Anweisungen verwendet werden, wir werden dies im späteren Teil dieses Tutorials sehen. - Wir können ein vorhandenes Enum erweitern, ohne eine vorhandene Funktionalität zu beeinträchtigen. Zum Beispiel können wir ein neues Feld
NEW
inThreadStates
hinzufügen, ohne eine vorhandene Funktionalität zu beeinflussen. - Da Enum-Felder Konstanten sind, ist es in Java am besten, sie in Großbuchstaben und mit Unterstrichen für Leerzeichen zu schreiben. Zum Beispiel
EAST
,WEST
,EAST_DIRECTION
usw. - Enum-Konstanten sind implizit
static
undfinal
. - Enum-Konstanten sind final, aber ihre Variablen können dennoch geändert werden. Zum Beispiel können wir die Methode
setPriority()
verwenden, um die Priorität der Enum-Konstanten zu ändern. Wir werden dies in einem späteren Beispiel sehen. - Da Enum-Konstanten final sind, können wir sie sicher mit
==
und der Methodeequals()
vergleichen. Beide haben dasselbe Ergebnis.
Java EnumSet, EnumMap, valueOf()
Nun, da wir die meisten Funktionen von Enum kennen, werfen wir einen Blick auf ein Java Enum-Beispielprogramm. Dann werden wir weitere Funktionen eines Enums kennenlernen.
package com.journaldev.enums;
import java.io.IOException;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Set;
public class JavaEnumExamples {
public static void main(String[] args) throws IOException {
usingEnumMethods();
usingEnumValueOf();
usingEnumValues();
usingEnumInSwitch(ThreadStatesEnum.START);
usingEnumInSwitch(ThreadStatesEnum.DEAD);
usingEnumMap();
usingEnumSet();
}
private static void usingEnumSet() {
EnumSet enumSet = EnumSet.allOf(ThreadStatesEnum.class);
for(ThreadStatesEnum tsenum : enumSet) {
System.out.println("Using EnumSet, priority = " + tsenum.getPriority());
}
}
private static void usingEnumMap() {
EnumMap<ThreadStatesEnum, String> enumMap = new EnumMap<>(ThreadStatesEnum.class);
enumMap.put(ThreadStatesEnum.START, "Thread ist gestartet");
enumMap.put(ThreadStatesEnum.RUNNING, "Thread läuft");
enumMap.put(ThreadStatesEnum.WAITING, "Thread wartet");
enumMap.put(ThreadStatesEnum.DEAD, "Thread ist tot");
Set keySet = enumMap.keySet();
for(ThreadStatesEnum key : keySet) {
System.out.println("key=" + key.toString() + ":: value=" + enumMap.get(key));
}
}
private static void usingEnumInSwitch(ThreadStatesEnum th) {
switch (th) {
case START:
System.out.println("START-Thread");
break;
case WAITING:
System.out.println("WAITING-Thread");
break;
case RUNNING:
System.out.println("RUNNING-Thread");
break;
case DEAD:
System.out.println("DEAD-Thread");
}
}
private static void usingEnumValues() {
ThreadStatesEnum[] thArray = ThreadStatesEnum.values();
for(ThreadStatesEnum th : thArray) {
System.out.println(th.toString() + "::priority=" + th.getPriority());
}
}
private static void usingEnumValueOf() {
ThreadStatesEnum th = Enum.valueOf(ThreadStatesEnum.class, "START");
System.out.println("th priority=" + th.getPriority());
}
private static void usingEnumMethods() throws IOException {
ThreadStatesEnum thc = ThreadStatesEnum.DEAD;
System.out.println("priority is:" + thc.getPriority());
thc = ThreadStatesEnum.DEAD;
System.out.println("Using overridden method." + thc.toString());
thc = ThreadStatesEnum.START;
System.out.println("Using overridden method." + thc.toString());
thc.setPriority(10);
System.out.println("Enum Constant variable changed priority value=" + thc.getPriority());
thc.close();
}
}