Enum in Java

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 erfahren wir, wie man ein Enum erstellt. Wir werden auch die Vorteile der Verwendung von Enums in Java und die Funktionen von Enum-Typen untersuchen. Wir lernen auch, wie man Java Enum valueOf, enum values, EnumSet und EnumMap mit Beispielen verwendet.

Java Enum Beispiel

Das Schlüsselwort enum wird verwendet, um einen Enum-Typ zu erstellen. Schauen wir uns das Java-Enum-Beispielprogramm an.

package com.journaldev.enums;

public enum ThreadStates {
	START,
	RUNNING,
	WAITING,
	DEAD;
}

In obigem Beispiel ist ThreadStates das Enum mit den festen Konstantenfeldern START, RUNNING, WAITING und DEAD.

Java Enum vs Konstanten

Schauen wir uns jetzt an, wie das Java-Enum besser ist als normale Konstantenfelder in Java-Klassen. 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;
}

Jetzt schauen wir uns an, wie sowohl Enums als auch Konstanten in einem Java-Programm verwendet werden:

/**
* This method shows the benefit of using Enum over Constants
*/
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 jeden int-Konstantenwert übergeben
	simpleConstantsExample(5);
}

private static void simpleEnumExample(ThreadStates th) {
	if(th == ThreadStates.START) System.out.println("Thread started");
	else if (th == ThreadStates.WAITING) System.out.println("Thread is waiting");
	else if (th == ThreadStates.RUNNING) System.out.println("Thread is running");
	else System.out.println("Thread is dead");
}
	
private static void simpleConstantsExample(int i) {
	if(i == ThreadStatesConstant.START) System.out.println("Thread started");
	else if (i == ThreadStatesConstant.WAITING) System.out.println("Thread is waiting");
	else if (i == ThreadStatesConstant.RUNNING) System.out.println("Thread is running");
	else System.out.println("Thread is dead");
}

Wenn wir uns das obige Beispiel ansehen, haben wir zwei Risiken bei der Verwendung von Konstanten, die durch das Enum gelöst werden.

  1. Wir können jeden int-Konstantenwert an die Methode simpleConstantsExample übergeben, aber wir können nur feste Werte an simpleEnumExample übergeben, was Typsicherheit bietet.
  2. Wir können den Wert der int-Konstanten in der Klasse ThreadStatesConstant ändern, aber das obige Programm wirft keine Ausnahme. Unser Programm funktioniert möglicherweise nicht wie erwartet, aber wenn wir die Enum-Konstanten ändern, erhalten wir einen Kompilierungsfehler, der jegliche Möglichkeit von Laufzeitproblemen beseitigt.

Java Enum Methoden

Jetzt schauen wir uns weitere Funktionen von Java Enum anhand eines Beispiels an.

package com.journaldev.enums;

import java.io.Closeable;
import java.io.IOException;

/**
 * This Enum example shows all the things we can do with Enum types
 *
 */
public enum ThreadStatesEnum implements Closeable{
	START(1){
		@Override
		public String toString(){
			return "START implementation. Priority="+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 "Default ThreadStatesConstructors implementation. Priority="+getPriority();
	}

	@Override
	public void close() throws IOException {
		System.out.println("Close of Enum");
	}
}

Wichtige Punkte zu Java Enum

Hier sind einige wichtige Punkte zu Enums in Java.

  1. Alle Java-Enums erweitern implizit die Klasse java.lang.Enum, die die Klasse Object erweitert und die Schnittstellen Serializable und Comparable implementiert. Daher können wir keine Klasse in einem Enum erweitern.
  2. Da Enum ein Schlüsselwort ist, kann der Paketname nicht damit enden. Zum Beispiel ist com.journaldev.enum kein gültiger Paketname.
  3. Enums können Schnittstellen implementieren. Wie im obigen Enum-Beispiel implementiert es die Schnittstelle Closeable.
  4. Enum-Konstruktoren sind immer privat.
  5. Wir können keine Instanz eines Enums mit dem new-Operator erstellen.
  6. Wir können abstrakte Methoden in Java-Enums 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.
  7. Wir können eine Methode im Enum definieren und die Enum-Felder können diese überschreiben. Zum Beispiel ist die Methode toString() im Enum definiert und das Enum-Feld START hat sie überschrieben.
  8. Java-Enum-Felder haben einen Namensraum, wir können ein Enum-Feld nur mit dem Klassennamen verwenden, z.B. ThreadStates.START
  9. Enums können in einer Switch-Anweisung verwendet werden, dies sehen wir später im Verlauf dieses Tutorials in Aktion.
  10. Wir können eine vorhandene Aufzählung erweitern, ohne die bestehende Funktionalität zu beeinträchtigen. Zum Beispiel können wir der Aufzählung „ThreadStates“ ein neues Feld „NEW“ hinzufügen, ohne die bestehende Funktionalität zu beeinträchtigen.
  11. Da die Felder einer Aufzählung Konstanten sind, ist es in Java bewährte Praxis, sie in Großbuchstaben und mit Unterstrichen für Leerzeichen zu schreiben. Zum Beispiel EAST, WEST, EAST_DIRECTION usw.
  12. Aufzählungskonstanten sind implizit statisch und final
  13. Aufzählungskonstanten sind final, aber ihre Variablen können dennoch geändert werden. Zum Beispiel können wir die Methode setPriority() verwenden, um die Priorität von Aufzählungskonstanten zu ändern. Wir werden dies im folgenden Beispiel sehen.
  14. Da Aufzählungskonstanten final sind, können wir sie sicher mit „==“ und der Methode equals() vergleichen. Beide liefern das gleiche Ergebnis.

Java EnumSet, EnumMap, valueOf()

Jetzt kennen wir die meisten Funktionen der Aufzählung. Werfen wir einen Blick auf ein Java-Beispielprogramm für Aufzählungen. Anschließend werden wir noch einige weitere Funktionen einer Aufzählung 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,String>(ThreadStatesEnum.class);
		enumMap.put(ThreadStatesEnum.START, "Thread is started");
		enumMap.put(ThreadStatesEnum.RUNNING, "Thread is running");
		enumMap.put(ThreadStatesEnum.WAITING, "Thread is waiting");
		enumMap.put(ThreadStatesEnum.DEAD, "Thread is dead");
		
		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 overriden method."+thc.toString());
		
		thc = ThreadStatesEnum.START;
		System.out.println("Using overriden method."+thc.toString());
		thc.setPriority(10);
		System.out.println("Enum Constant variable changed priority value="+thc.getPriority());
		thc.close();
	}

}

Bevor wir andere wichtige Funktionen einer Aufzählung erklären, werfen wir einen Blick auf die Ausgabe des obigen Programms.

priority is:4
Using overriden method.Default ThreadStatesConstructors implementation. Priority=4
Using overriden method.START implementation. Priority=1
Enum Constant variable changed priority value=10
Close of Enum
th priority=10
START implementation. Priority=10::priority=10
Default ThreadStatesConstructors implementation. Priority=2::priority=2
Default ThreadStatesConstructors implementation. Priority=3::priority=3
Default ThreadStatesConstructors implementation. Priority=4::priority=4
START thread
DEAD thread
key=START:: value=Thread is started
key=RUNNING:: value=Thread is running
key=WAITING:: value=Thread is waiting
key=DEAD:: value=Thread is dead
Using EnumSet, priority = 10
Using EnumSet, priority = 2
Using EnumSet, priority = 3
Using EnumSet, priority = 4

Wichtige Punkte

  1. Die Methode usingEnumMethods() zeigt, wie man ein Enum-Objekt erstellt und seine Methoden verwendet. Sie zeigt auch die Verwendung der Methode setPriority(int i), um die Variable des Enums zu ändern.
  2. Die Methode usingEnumValueOf() zeigt die Verwendung von java.util.Enum valueOf(enumType, name), mit der wir ein Enum-Objekt aus einem String erstellen können. Sie wirft eine IllegalArgumentException aus, wenn der angegebene Enum-Typ keine Konstante mit dem angegebenen Namen hat oder das angegebene Klassenobjekt keinen Enum-Typ darstellt. Sie wirft auch eine NullPointerException aus, wenn eines der Argumente null ist.
  3. Die Methode usingEnumValues() zeigt die Verwendung der Methode values(), die ein Array mit allen Werten des Enums in der Reihenfolge, in der sie deklariert sind, zurückgibt. Beachten Sie, dass diese Methode automatisch vom Java-Compiler für jedes Enum generiert wird. Sie finden die Implementierung von values() nicht in der Klasse java.util.Enum.
  4. Die Methode usingEnumInSwitch() zeigt, wie man Enum-Konstanten in einer Switch-Anweisung verwendet.
  5. Die Methode usingEnumMap() zeigt die Verwendung von java.util.EnumMap, die in der Java 1.5 Collections Framework eingeführt wurde. EnumMap ist eine Map-Implementierung zur Verwendung mit Enum-Typ-Schlüsseln. Alle Schlüssel in einer Enum-Map müssen aus einem einzigen Enum-Typ stammen, der explizit oder implizit beim Erstellen der Map angegeben wird. Wir können null nicht als Schlüssel für EnumMap verwenden und EnumMap ist nicht synchronisiert.
  6. usingEnumSet() Methode zeigt die Verwendung von java.util.EnumSet, das eine Set-Implementierung für die Verwendung mit Enum-Typen ist. Alle Elemente in einem Enum-Set müssen aus einem einzigen Enum-Typ stammen, der explizit oder implizit angegeben ist, wenn das Set erstellt wird. EnumSet ist nicht synchronisiert und Null-Elemente sind nicht erlaubt. Es bietet auch einige nützliche Methoden wie copyOf(Collection<E> c), of(E first, E... rest) und complementOf(EnumSet<E> s).

Sie können alle Beispiele aus unserem GitHub Repository überprüfen.

Referenz: Oracle Doc

Source:
https://www.digitalocean.com/community/tutorials/java-enum