Un statut, un niveau d’accès ou un jour de la semaine ne devrait pas être représenté par une chaîne saisie au hasard. En Java, une énumération permet de limiter proprement les valeurs possibles, de sécuriser le code à la compilation et d’associer un comportement à chaque choix. Je présente ici sa syntaxe, ses méthodes utiles, ses usages avec switch, ainsi que les pièges à éviter dans une application réelle.
Une énumération Java rend les choix fixes plus sûrs et plus lisibles
- Définition : un type enum représente un ensemble fermé de constantes nommées.
- Sécurité : le compilateur refuse une valeur qui n’appartient pas à l’énumération.
- Comportement : chaque constante peut posséder des champs, un constructeur et des méthodes.
-
API utile :
values(),valueOf(),name()etEnumSetcouvrent les besoins courants. - Point de vigilance : une enum est stable pour un domaine fermé, mais peu adaptée à des valeurs configurables.
Pourquoi utiliser une enum plutôt qu’une chaîne ou un entier
Une enum est un type de données limité à des constantes prédéfinies. Elle convient lorsque toutes les valeurs possibles sont connues au moment de la compilation, par exemple EN_ATTENTE, PAYEE et ANNULEE pour une commande.
public enum StatutCommande {
EN_ATTENTE,
PAYEE,
ANNULEE
}
StatutCommande statut = StatutCommande.PAYEE;
Le principal avantage est la lisibilité. StatutCommande.PAYEE indique clairement l’intention, alors qu’un entier comme 2 oblige à consulter une documentation ou une constante. Le compilateur apporte aussi une vérification de type qui élimine une partie des erreurs silencieuses.
| Solution | Atout | Limite |
|---|---|---|
enum |
Valeurs contrôlées et code lisible | La liste est définie dans le code |
String |
Flexible pour les données externes | Fautes de frappe et valeurs inattendues |
int |
Simple à stocker dans certains anciens systèmes | Le sens des nombres est difficile à comprendre |
| Classe classique | Adaptée aux objets extensibles | Plus lourde pour une liste fermée de choix |
Dans mes projets, je choisis presque toujours l’enum dès qu’un champ possède un nombre réduit de valeurs stables. Je préfère réserver les chaînes aux entrées externes, puis les convertir immédiatement en type métier afin de ne pas laisser cette incertitude circuler dans toute l’application.
Déclarer une enum et l’utiliser correctement
La déclaration utilise le mot-clé enum. Les constantes sont généralement écrites en majuscules et séparées par des virgules. Elles sont créées par Java et ne peuvent pas être instanciées avec new.
public enum Priorite {
BASSE,
NORMALE,
HAUTE,
URGENTE
}
Priorite priorite = Priorite.HAUTE;
if (priorite == Priorite.URGENTE) {
System.out.println("Traitement immédiat");
}
Pour comparer deux constantes, j’utilise directement ==. Cette comparaison est sûre, car chaque constante représente une instance unique de son type. L’appel à equals() fonctionne aussi, mais il est moins direct et peut provoquer une erreur si la valeur de gauche est null.
Parcourir toutes les constantes
La méthode values() renvoie les constantes dans leur ordre de déclaration. C’est pratique pour remplir une liste d’options ou afficher les choix disponibles.
for (Priorite priorite : Priorite.values()) {
System.out.println(priorite);
}
Je déconseille cependant de faire dépendre une logique métier de cet ordre. Ajouter une constante au milieu de l’enum modifierait sa position, et la méthode ordinal() ne doit pas servir d’identifiant persistant en base de données.
Convertir un nom en constante
valueOf() recherche une constante à partir de son nom exact. Elle distingue les majuscules et lève une IllegalArgumentException si le nom n’existe pas.
Priorite priorite = Priorite.valueOf("HAUTE");
Pour une valeur fournie par un formulaire ou une API, je normalise et je contrôle toujours l’entrée avant cet appel. Dans le cas contraire, une simple faute de casse peut transformer une donnée utilisateur en exception non gérée.
Ajouter des champs et un comportement métier
Une enum Java n’est pas une simple liste de mots. Elle définit une classe spécialisée qui peut contenir des champs, des méthodes et un constructeur privé ou package-private. C’est particulièrement utile lorsque chaque constante possède un code technique ou une règle propre.
public enum NiveauAcces {
LECTURE("read"),
ECRITURE("write"),
ADMINISTRATION("admin");
private final String code;
NiveauAcces(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
Les constantes doivent apparaître avant les champs et les méthodes. Dès qu’elles sont suivies d’un corps de classe, un point-virgule termine la liste. Ce détail paraît mineur, mais il explique beaucoup d’erreurs de syntaxe chez les débutants.
Associer une méthode à chaque constante
Je préfère souvent placer la règle près de la donnée plutôt que de multiplier les switch dans les services. Chaque constante peut redéfinir une méthode abstraite et porter son propre comportement.
public enum FormatFichier {
CSV {
@Override
public String extension() {
return ".csv";
}
},
JSON {
@Override
public String extension() {
return ".json";
}
};
public abstract String extension();
}
Cette approche reste élégante pour quelques variantes cohérentes. Si le comportement devient très volumineux ou dépend de nombreux services externes, une stratégie séparée sera plus facile à tester et à faire évoluer.
Utiliser une interface avec une enum
Une enum ne peut pas étendre une autre classe, car elle hérite déjà implicitement de java.lang.Enum. Elle peut toutefois implémenter une ou plusieurs interfaces, ce qui offre une bonne solution pour partager un contrat commun.
public interface Libellable {
String libelle();
}
public enum Couleur implements Libellable {
ROUGE("Rouge"),
BLEU("Bleu");
private final String libelle;
Couleur(String libelle) {
this.libelle = libelle;
}
@Override
public String libelle() {
return libelle;
}
}

Combiner les enums avec switch, EnumSet et EnumMap
Les énumérations prennent tout leur sens lorsqu’elles alimentent une logique de décision. Un switch rend les cas visibles et permet au compilateur de signaler plus facilement une branche manquante selon la forme utilisée.
String message = switch (statut) {
case EN_ATTENTE -> "Commande en préparation";
case PAYEE -> "Paiement confirmé";
case ANNULEE -> "Commande annulée";
};
Cette expression renvoie directement une valeur et évite les variables temporaires. Je recommande d’éviter un default automatique lorsque l’exhaustivité est importante, car l’ajout futur d’une constante ne provoquerait alors pas forcément d’alerte claire lors de la compilation.
Gérer un ensemble de constantes
EnumSet est conçu pour stocker efficacement plusieurs valeurs d’une même enum. Il est plus expressif qu’un ensemble de chaînes et garantit que toutes les valeurs appartiennent au bon type.
EnumSet prioritesCritiques =
EnumSet.of(Priorite.HAUTE, Priorite.URGENTE);
if (prioritesCritiques.contains(priorite)) {
System.out.println("Escalade nécessaire");
}
Associer une donnée à chaque constante
Avec EnumMap, la clé est obligatoirement une enum. C’est mon choix préféré lorsqu’il faut associer une configuration légère à chaque état sans créer une chaîne de caractères fragile.
EnumMap delaisEnHeures =
new EnumMap<>(Priorite.class);
delaisEnHeures.put(Priorite.BASSE, 72);
delaisEnHeures.put(Priorite.NORMALE, 24);
delaisEnHeures.put(Priorite.HAUTE, 4);
Éviter les erreurs lors des API, bases de données et fichiers
Le nom d’une constante n’est pas toujours le bon format pour communiquer avec un système externe. Une API peut attendre "in_progress", tandis que Java utilise EN_COURS. Je sépare donc le nom interne du code d’échange.
public enum StatutTicket {
OUVERT("open"),
EN_COURS("in_progress"),
FERME("closed");
private final String code;
StatutTicket(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public static StatutTicket fromCode(String code) {
for (StatutTicket statut : values()) {
if (statut.code.equals(code)) {
return statut;
}
}
throw new IllegalArgumentException("Code inconnu : " + code);
}
}
Cette méthode centralise la conversion et rend l’erreur explicite. Pour des données réellement facultatives, je préfère retourner un résultat contrôlé ou gérer clairement la valeur absente plutôt que de masquer le problème avec une valeur par défaut arbitraire.
Lire aussi : LocalDateTime en Instant - Évitez les pièges de l'heure d'été
Attention à la persistance
En base de données, stocker l’ordinal est risqué, car l’ordre peut changer. Un code explicite ou le nom de la constante est généralement plus stable, à condition de définir une règle de migration si une valeur doit être renommée.
Pour les formats publics, je considère le code de l’enum comme un contrat. Une modification de "closed" vers "done" peut casser des clients, des fichiers historiques ou des tableaux de bord, même si le code Java compile parfaitement.
Savoir quand une enum n’est pas le bon choix
Une enum convient à un ensemble fermé et connu à l’avance. Elle devient moins pertinente si les valeurs sont ajoutées par un administrateur, chargées depuis une base ou modifiées sans redéployer l’application.
- Pour des devises configurables, utilisez plutôt une table de référence.
- Pour des rôles créés par les utilisateurs, préférez une entité persistante.
- Pour un état strictement contrôlé par le code, gardez l’enum.
- Pour des valeurs venant d’une API externe, utilisez un code explicite et une conversion dédiée.
Je me méfie aussi des enums trop ambitieuses qui contiennent des appels réseau, des règles d’autorisation ou des dépendances complexes. Leur simplicité est une force, mais elle disparaît lorsque la classe devient un service déguisé.
Enfin, évitez de confondre name() et toString(). Le premier renvoie le nom exact de la constante, tandis que le second peut être redéfini pour l’affichage. Pour un stockage ou une API, un champ comme code est souvent plus clair et plus durable.
Le bon réflexe pour concevoir une enum durable
Avant de créer une enum, je vérifie trois points simples. Les valeurs sont-elles réellement limitées, leur ajout nécessite-t-il une modification du code, et doivent-elles être échangées avec un système externe ? Si les deux premières réponses sont positives, l’enum est probablement adaptée.
Je donne ensuite à chaque constante un nom métier clair, j’ajoute un code externe lorsque c’est nécessaire et je teste les conversions inconnues. Cette discipline évite les erreurs les plus coûteuses, notamment les ordinals persistés et les chaînes dispersées dans toute l’application.
Bien utilisée, une énumération Java reste l’un des outils les plus simples pour rendre un domaine explicite, sécuriser les décisions du programme et maintenir un code lisible quand le projet grandit.