Enum en Java

Enum

a été introduit en Java 1.5 en tant que nouveau type dont les champs consistent en un ensemble fixe de constantes. Par exemple, nous pouvons créer des directions en tant qu’Enum Java avec des champs fixes tels que EAST, WEST, NORTH et SOUTH.

Exemple d’Enum Java

Le mot-clé enum en Java est utilisé pour créer un type enum. Jetons un coup d’œil au programme d’exemple d’enum Java.

package com.journaldev.enums;

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

Dans l’exemple ci-dessus, ThreadStates est l’enum avec des champs constants fixes START, RUNNING, WAITING et DEAD.

Enum Java vs Constantes

Maintenant, voyons comment l’enum Java est meilleur que les champs constants normaux dans les classes Java. Créons une classe de constantes similaire en 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;
}

Maintenant, voyons comment les enumérations et les constantes sont utilisées dans un programme Java :

/**
* This method shows the benefit of using Enum over Constants
*/
private static void benefitsOfEnumOverConstants() {
	 // Les valeurs d'énumération sont fixes 
	simpleEnumExample(ThreadStates.START);
	simpleEnumExample(ThreadStates.WAITING);
	simpleEnumExample(ThreadStates.RUNNING);
	simpleEnumExample(ThreadStates.DEAD);
	simpleEnumExample(null);
		
	simpleConstantsExample(1);
	simpleConstantsExample(2);
	simpleConstantsExample(3);
	simpleConstantsExample(4);
	 // Nous pouvons passer n'importe quelle constante int 
	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");
}

Si nous regardons l’exemple ci-dessus, nous avons deux risques avec l’utilisation de constantes qui sont résolus par l’énumération.

  1. Nous pouvons passer n’importe quelle constante int à la méthode simpleConstantsExample, mais nous pouvons passer uniquement des valeurs fixes à simpleEnumExample, donc cela assure la sécurité des types.
  2. Nous pouvons modifier la valeur des constantes int dans la classe ThreadStatesConstant, mais le programme ci-dessus ne lancera aucune exception. Notre programme pourrait ne pas fonctionner comme prévu, mais si nous modifions les constantes de l’énumération, nous obtiendrons une erreur de compilation qui élimine toute possibilité de problèmes d’exécution.

Méthodes d’énumération Java

Maintenant, voyons plus de fonctionnalités des énumérations Java avec un exemple.

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();
	 // Les constructeurs d'énumération doivent toujours être privés. 
	private ThreadStatesEnum(int i){
		priority = i;
	}
	
	 // L'énumération peut avoir des méthodes 
	public int getPriority(){
		return this.priority;
	}
	
	public void setPriority(int p){
		this.priority = p;
	}
	
	 // L'énumération peut remplacer des fonctions 
	@Override
	public String toString(){
		return "Default ThreadStatesConstructors implementation. Priority="+getPriority();
	}

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

Points Importants sur les Enumérations Java

Voici quelques points importants pour les énumérations en Java.

  1. Tous les énumérations Java étendent implicitement la classe java.lang.Enum, qui elle-même étend la classe Object et implémente les interfaces Serializable et Comparable. Ainsi, il n’est pas possible d’étendre une autre classe dans une énumération.
  2. Comme « enum » est un mot-clé, il n’est pas autorisé de terminer le nom d’un package par celui-ci. Par exemple, com.journaldev.enum n’est pas un nom de package valide.
  3. Une énumération peut implémenter des interfaces, comme illustré dans l’exemple ci-dessus où elle implémente l’interface Closeable.
  4. Les constructeurs des énumérations sont toujours privés.
  5. Il n’est pas possible de créer une instance d’une énumération à l’aide de l’opérateur « new ».
  6. Nous pouvons déclarer des méthodes abstraites en Java dans une énumération. Dans ce cas, tous les champs de l’énumération doivent implémenter la méthode abstraite. Dans l’exemple ci-dessus, getDetail() est la méthode abstraite, et tous les champs de l’énumération l’implémentent.
  7. Nous pouvons définir une méthode dans une énumération, et les champs de l’énumération peuvent également les remplacer. Par exemple, la méthode toString() est définie dans l’énumération, et le champ START l’a remplacée.
  8. Les champs des énumérations Java ont un espace de noms ; nous pouvons utiliser un champ d’énumération uniquement avec le nom de la classe, comme ThreadStates.START.
  9. Les énumérations peuvent être utilisées dans une instruction switch, comme nous le verrons plus tard dans ce tutoriel.
  10. Nous pouvons étendre une énumération existante sans compromettre sa fonctionnalité existante. Par exemple, nous pouvons ajouter un nouveau champ « NEW » dans l’énumération ThreadStates sans affecter aucune fonctionnalité existante.
  11. Étant donné que les champs d’énumération sont des constantes, la meilleure pratique en Java est de les écrire en lettres majuscules et de les séparer par des underscores pour les espaces. Par exemple, EAST, WEST, EAST_DIRECTION, etc.
  12. Les constantes d’énumération sont implicitement statiques et finales.
  13. Les constantes d’énumération sont finales, mais leurs variables peuvent néanmoins être modifiées. Par exemple, nous pouvons utiliser la méthode setPriority() pour changer la priorité des constantes d’énumération. Nous le verrons dans l’exemple ci-dessous.
  14. Étant donné que les constantes d’énumération sont finales, nous pouvons les comparer en toute sécurité à l’aide des opérateurs « == » et equals(). Les deux donneront le même résultat.

Java EnumSet, EnumMap, valueOf()

Maintenant que nous connaissons la plupart des fonctionnalités des énumérations, examinons un exemple de programme Java utilisant des énumérations. Ensuite, nous apprendrons d’autres fonctionnalités d’une énumération.

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

}

Avant d’expliquer d’autres fonctionnalités importantes des énumérations, examinons la sortie du programme ci-dessus.

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

Points importants

  1. Le usingEnumMethods() montre comment créer un objet enum et comment utiliser ses méthodes. Il montre également l’utilisation de la méthode setPriority(int i) pour modifier la variable d’énumération.
  2. usingEnumValueOf() présente l’utilisation de java.util.Enum valueOf(enumType, name), à travers laquelle nous pouvons créer un objet enum à partir d’une chaîne de caractères. Cela génère une IllegalArgumentException si le type d’énumération spécifié n’a pas de constante avec le nom spécifié, ou si l’objet de classe spécifié ne représente pas un type énumération. Cela génère également une NullPointerException si l’un des arguments est nul.
  3. usingEnumValues() montre l’utilisation de la méthode values() qui renvoie un tableau contenant toutes les valeurs de l’énumération dans l’ordre de leur déclaration. Notez que cette méthode est automatiquement générée par le compilateur Java pour chaque énumération. Vous ne trouverez pas l’implémentation de values() dans la classe java.util.Enum.
  4. La méthode usingEnumInSwitch() montre comment utiliser les constantes enum dans une structure switch.
  5. La méthode usingEnumMap() montre l’utilisation de java.util.EnumMap, introduite dans le framework Collections Java 1.5. EnumMap est une implémentation de Map destinée aux clés de type enum. Toutes les clés dans une enum map doivent provenir d’un seul type énumération spécifié de manière explicite ou implicite lors de la création de la map. Nous ne pouvons pas utiliser null comme clé pour EnumMap et EnumMap n’est pas synchronisé.
  6. La méthode usingEnumSet() montre l’utilisation de java.util.EnumSet, qui est une implémentation de Set pour une utilisation avec des types enum. Tous les éléments dans un ensemble enum doivent provenir d’un seul type enum spécifié, explicitement ou implicitement, lorsque l’ensemble est créé. EnumSet n’est pas synchronisé et les éléments nuls ne sont pas autorisés. Il fournit également quelques méthodes utiles comme copyOf(Collection<E> c), of(E first, E... rest) et complementOf(EnumSet<E> s).

Vous pouvez consulter tous les exemples sur notre Repository GitHub.

Référence: Oracle Doc

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