Enum in Java

Enum werd geïntroduceerd in Java 1.5 als een nieuw type waarvan de velden bestaan uit een vast aantal constanten. Bijvoorbeeld, we kunnen richtingen maken als een Java Enum met vaste velden zoals EAST, WEST, NORTH, en SOUTH.

Java Enum

In deze tutorial zullen we leren hoe we een Enum kunnen maken. We zullen ook kijken naar de voordelen van het gebruik van enums in Java en de kenmerken van enum types. We zullen ook leren hoe we Java Enum valueOf, enum values, EnumSet en EnumMap kunnen gebruiken met voorbeelden.

Voorbeeld van Java Enum

Het Java enum trefwoord wordt gebruikt om een enum type te maken. Laten we eens kijken naar het voorbeeldprogramma van de Java enum.

package com.journaldev.enums;

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

In het bovenstaande voorbeeld is ThreadStates de enum met vaste constante velden START, RUNNING, WAITING en DEAD.

Vergelijking tussen Java Enum en Constanten

Laten we nu eens kijken hoe Java enum beter is dan normale constante velden in Java-klassen. Laten we een vergelijkbare constante klasse maken 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;
}

Nu gaan we eens kijken hoe zowel enum als constanten worden gebruikt in een Java-programma:

/**
* This method shows the benefit of using Enum over Constants
*/
private static void benefitsOfEnumOverConstants() {
	//Enum-waarden zijn vast
	simpleEnumExample(ThreadStates.START);
	simpleEnumExample(ThreadStates.WAITING);
	simpleEnumExample(ThreadStates.RUNNING);
	simpleEnumExample(ThreadStates.DEAD);
	simpleEnumExample(null);
		
	simpleConstantsExample(1);
	simpleConstantsExample(2);
	simpleConstantsExample(3);
	simpleConstantsExample(4);
	//we kunnen elk constant int doorgeven
	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");
}

Als we naar het bovenstaande voorbeeld kijken, hebben we twee risico’s bij het gebruik van constanten die worden opgelost door de enum.

  1. We kunnen elk int-constante doorgeven aan de methode simpleConstantsExample maar we kunnen alleen vaste waarden doorgeven aan simpleEnumExample, dus het biedt typeveiligheid.
  2. We kunnen de waarde van de int-constanten wijzigen in de klasse ThreadStatesConstant maar het bovenstaande programma zal geen uitzondering veroorzaken. Ons programma werkt mogelijk niet zoals verwacht, maar als we de enum-constanten wijzigen, krijgen we een compileerfout die elk mogelijk runtime-probleem wegneemt.

Java Enum-methoden

Latenn we nu meer functies van Java Enum zien aan de hand van een voorbeeld.

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-constructors moeten altijd privé zijn.
	private ThreadStatesEnum(int i){
		priority = i;
	}
	
	//Enum kan methoden hebben
	public int getPriority(){
		return this.priority;
	}
	
	public void setPriority(int p){
		this.priority = p;
	}
	
	//Enum kan functies overschrijven
	@Override
	public String toString(){
		return "Default ThreadStatesConstructors implementation. Priority="+getPriority();
	}

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

Belangrijke punten van Java Enum

Hier zijn enkele belangrijke punten voor Enums in Java.

  1. Alle java enumeraties breiden impliciet de klasse java.lang.Enum uit, die de klasse Object uitbreidt en de interfaces Serializable en Comparable implementeert. We kunnen dus geen enkele klasse uitbreiden in een enumeratie.
  2. Aangezien enumeratie een trefwoord is, kunnen we de pakketnaam er niet mee eindigen, bijvoorbeeld com.journaldev.enum is geen geldige pakketnaam.
  3. Een enumeratie kan interfaces implementeren. Zoals in het bovenstaande enumeratievoorbeeld, implementeert het de interface Closeable.
  4. De constructors van een enumeratie zijn altijd privé.
  5. We kunnen geen instantie van een enumeratie maken met behulp van de nieuwe operator.
  6. We kunnen abstracte methoden in java enumeraties declareren, waarna alle enumeratievelden de abstracte methode moeten implementeren. In het bovenstaande voorbeeld is getDetail() de abstracte methode en hebben alle enumeratievelden deze geïmplementeerd.
  7. We kunnen een methode in een enumeratie definiëren en de enumeratievelden kunnen deze ook overschrijven. Bijvoorbeeld, de toString()-methode is gedefinieerd in de enumeratie en het enumeratieveld START heeft deze overschreven.
  8. Java enumeratievelden hebben een namespace, we kunnen enumeratievelden alleen gebruiken met de klassenaam zoals ThreadStates.START
  9. Enumeraties kunnen worden gebruikt in een switch statement, we zullen dit in actie zien in het latere deel van deze tutorial.
  10. We kunnen een bestaande enum uitbreiden zonder enige bestaande functionaliteit te breken. Bijvoorbeeld, we kunnen een nieuw veld NEW toevoegen aan de ThreadStates enum zonder enige bestaande functionaliteit te beïnvloeden.
  11. Aangezien enum-velden constanten zijn, is de Java-best practice om ze in hoofdletters en met een underscore voor spaties te schrijven. Bijvoorbeeld EAST, WEST, EAST_DIRECTION, enzovoort.
  12. Enum-constanten zijn impliciet static en final
  13. Enum-constanten zijn final, maar de variabele kan nog steeds worden gewijzigd. Bijvoorbeeld, we kunnen de setPriority() methode gebruiken om de prioriteit van enum-constanten te wijzigen. We zullen dit zien in het gebruik in het onderstaande voorbeeld.
  14. Aangezien enum-constanten final zijn, kunnen we ze veilig vergelijken met behulp van de “==” operator en de equals() methoden. Beide zullen hetzelfde resultaat hebben.

Java EnumSet, EnumMap, valueOf()

Nu we de meeste kenmerken van Enum kennen, laten we eens kijken naar een voorbeeld van een Java Enum-programma. Daarna zullen we nog wat meer kenmerken van een enum leren.

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();
	}

}

Voordat we andere belangrijke kenmerken van enum uitleggen, laten we eerst de uitvoer van het bovenstaande programma zien.

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

Belangrijke punten

  1. De methode usingEnumMethods() laat zien hoe je een enum-object kunt maken en hoe we de methoden ervan kunnen gebruiken. Het toont ook het gebruik van de methode setPriority(int i) om de variabele van de enum te veranderen.
  2. De methode usingEnumValueOf() laat het gebruik zien van java.util.Enum valueOf(enumType, name) waarmee we een enum-object kunnen maken vanuit een tekenreeks. Het werpt een IllegalArgumentException op als het gespecificeerde enum-type geen constante heeft met de opgegeven naam, of het gespecificeerde klassenobject geen enum-type vertegenwoordigt. Het werpt ook een NullPointerException op als een van de argumenten null is.
  3. De methode usingEnumValues() toont het gebruik van de values()-methode die een array retourneert met alle waarden van de enum in de volgorde waarin ze zijn gedeclareerd. Merk op dat deze methode automatisch wordt gegenereerd door de Java-compiler voor elke enum. Je zult de implementatie van values() niet vinden in de klasse java.util.Enum.
  4. De methode usingEnumInSwitch() laat zien hoe enum-constanten kunnen worden gebruikt in een switch-case.
  5. De methode usingEnumMap() laat het gebruik zien van java.util.EnumMap, die is geïntroduceerd in de Java 1.5-collectiekader. EnumMap is een map-implementatie voor gebruik met enum-type sleutels. Alle sleutels in een enum-map moeten afkomstig zijn van één enkel enum-type dat expliciet of impliciet wordt gespecificeerd wanneer de map wordt gemaakt. We kunnen null niet als sleutel gebruiken voor EnumMap en EnumMap is niet gesynchroniseerd.
  6. usingEnumSet() methode toont het gebruik van java.util.EnumSet, wat een Set-implementatie is voor gebruik met enum-types. Alle elementen in een enum-set moeten afkomstig zijn van één enkel enum-type dat wordt gespecificeerd, expliciet of impliciet, wanneer de set wordt gemaakt. EnumSet is niet gesynchroniseerd en null-elementen zijn niet toegestaan. Het biedt ook enkele nuttige methoden zoals copyOf(Collection<E> c), of(E first, E... rest) en complementOf(EnumSet<E> s).

U kunt alle voorbeelden bekijken op onze GitHub Repository.

Referentie: Oracle Doc

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