Menu

Les énumérations Java : un ensemble fixe de constantes nommées

Ce qu'est une énumération Java, comment la déclarer, lui ajouter des champs et des méthodes, l'utiliser dans un switch, et pourquoi une enum vaut mieux qu'un tas de constantes int ou String.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

Un ensemble fixe de valeurs nommées

Certaines valeurs n'ont de sens que comme élément d'une petite liste connue : les jours de la semaine, les couleurs d'un jeu de cartes, les états dans lesquels une commande peut se trouver. Vous pourriez les modéliser avec des codes int (0 pour en attente, 1 pour expédié) ou des chaînes ("PENDING", "SHIPPED"), mais rien n'empêche un appelant de passer 7 ou "PNEDING". Une enum comble cette faille — le type lui-même n'autorise que les valeurs que vous avez déclarées.

Day est un tout nouveau type. Une variable de type Day peut contenir exactement l'une de ces sept constantes (ou null) et rien d'autre. Le compilateur rejette Day d = "WEDNESDAY"; ou Day d = 2;. C'est précisément le but de cette garantie.

Chaque constante (Day.MONDAY, etc.) est une instance partagée unique, créée une seule fois. Comme il n'existe qu'un seul MONDAY, vous comparez les enums avec == plutôt qu'avec equals — ce sont le même objet.

Faire un switch sur une énumération

Les énumérations s'accordent naturellement avec switch. Vous n'avez même pas besoin de qualifier chaque constante par le nom du type à l'intérieur du switch :

À l'intérieur du switch, écrivez case SATURDAY, pas case Day.SATURDAY — Java infère le type. Le grand avantage par rapport à un switch sur une chaîne ou un int, c'est que si vous ajoutez une nouvelle constante plus tard, votre IDE et les vérifications d'exhaustivité peuvent signaler chaque switch qui a oublié de la traiter.

Parcourir toutes les constantes

Chaque enum reçoit automatiquement une méthode statique values() qui renvoie toutes ses constantes dans l'ordre de déclaration, ainsi qu'une méthode ordinal() donnant la position de chaque constante en commençant à zéro :

name() donne l'identifiant de la constante sous forme de String, et values() est parfait pour construire des menus ou itérer sur des options. Une mise en garde : ne stockez pas ordinal() dans un emplacement persistant. Si quelqu'un réordonne les constantes par la suite, les numéros décalent et vos données enregistrées sont corrompues. Considérez ordinal() comme un détail d'implémentation, pas comme un identifiant stable.

Les énumérations sont de vraies classes : champs et méthodes

C'est là que les énumérations Java vont au-delà des enums d'entiers nommés des autres langages. Chaque constante peut porter des données, transmises via un constructeur, et l'enum peut avoir des méthodes. Vous listez d'abord les constantes, donnez à chacune ses arguments de constructeur, puis déclarez les champs, le constructeur et les méthodes après un point-virgule.

Remarquez la structure : les constantes viennent en premier et se terminent par un point-virgule, puis le reste de la classe suit. Le constructeur est implicitement private — vous ne pouvez jamais écrire new Planet(...), car les seules instances autorisées sont celles déclarées en haut. Les champs final rendent chaque constante immuable, ce qui est exactement ce que l'on veut pour des singletons partagés.

D'une chaîne et retour

Pour transformer une chaîne en la constante correspondante, utilisez le valueOf généré automatiquement :

valueOf fait correspondre le nom de la constante de façon exacte, casse comprise, et lève IllegalArgumentException s'il n'y a pas de correspondance. C'est le piège classique : "shipped" ne correspond pas à SHIPPED. Lors de l'analyse d'une saisie utilisateur ou de données externes, normalisez d'abord la casse (input.toUpperCase()) et entourez l'appel d'un try/catch, sinon vous planterez dès la première valeur incorrecte.

Comportement propre à chaque constante

Parfois, chaque constante doit se comporter différemment, et pas seulement contenir des données différentes. Vous pouvez doter une enum d'une méthode abstraite et faire en sorte que chaque constante fournisse sa propre implémentation dans un petit corps :

On parle parfois du motif « méthode spécifique à une constante ». Il remplace un switch tentaculaire sur la constante par un comportement attaché directement à chacune — ajoutez une nouvelle opération et le compilateur vous force à définir son apply, ce qui vous empêche d'oublier un cas.

Quand recourir à une énumération

Utilisez une enum chaque fois qu'une valeur est naturellement l'élément d'un ensemble petit, fixe et connu à la compilation :

  • Les états d'un flux de travail (PENDING, SHIPPED, DELIVERED).
  • Les catégories, modes ou types (READ, WRITE, EXECUTE).
  • Partout où vous étiez tenté de définir un groupe de constantes public static final int — l'enum vous offre les mêmes valeurs nommées plus la sûreté de typage, un toString lisible et la prise en charge du switch sans effort.

N'utilisez pas d'enum pour un ensemble ouvert ou déterminé à l'exécution (noms d'utilisateurs, liste de pays tirée d'une base de données). Les énumérations sont figées à la compilation ; si l'ensemble change pendant l'exécution du programme, vous voulez plutôt une collection ordinaire.

Suite : Les génériques

Vous avez désormais vu values() renvoyer un Planet[] et, dans les pages précédentes, l'usage de List<Shape> — cette syntaxe <...>, ce sont les génériques, la façon dont Java permet d'écrire une seule classe ou méthode fonctionnant pour de nombreux types tout en conservant une sûreté de typage complète. Nous allons ensuite décortiquer le fonctionnement réel de List<String> et Map<K, V> et la manière d'écrire vos propres types génériques.

Questions fréquentes

Qu'est-ce qu'une énumération en Java ?

Une enum est un type particulier dont la valeur ne peut être que l'une d'un ensemble fixe de constantes nommées, comme Day.MONDAY ou Status.ACTIVE. Chaque constante est une instance unique de l'enum, créée une seule fois. Les énumérations apportent la sûreté de typage : une méthode qui prend un Day ne peut recevoir qu'un jour réel, jamais une chaîne mal orthographiée ni un int hors plage.

Une énumération Java peut-elle avoir des champs et des méthodes ?

Oui. Une enum est une classe à part entière. Vous pouvez passer des arguments au constructeur de chaque constante, les stocker dans des champs private final et ajouter des méthodes qui les utilisent. Par exemple, MERCURY(3.3e23, 2.4e6) transmet la masse et le rayon au constructeur de l'enum, et une méthode surfaceGravity() peut calculer un résultat à partir de ces champs.

Quelle est la différence entre values() et valueOf() sur une énumération Java ?

values() renvoie un tableau de toutes les constantes de l'enum, dans l'ordre de déclaration — pratique pour parcourir chaque option. valueOf("NAME") fait l'inverse : il recherche la constante dont le nom correspond exactement à la chaîne, et lève IllegalArgumentException si aucune ne correspond. Les deux sont générés automatiquement par le compilateur.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER