6. Énumérations

Les énumérations sont un ajout de Java 5, ce qui suit dans ce paragraphe ne concerne donc pas les versions antérieures de Java. Une énumération est un type de données particulier, dans lequel une variable ne peut prendre qu'un nombre restreint de valeurs. Ces valeurs sont des constantes nommées, par exemple MADAME, MADEMOISELLE, MONSIEUR.

6.1. Déclaration d'une énumération

La façon la plus simple de déclarer une énumération consiste à l'écrire lorsque l'on crée une variable, comme dans le code qui suit.

Exemple 38. Une première énumération

enum Civilite {MADAME, MADEMOISELLE, MONSIEUR} ;  
    Civilite civilite = Civilite.MADAME ;

La première ligne de ce code déclare l'énumération proprement dite. La deuxième ligne instancie une variable de type Civilite (exactement comme si Civilite était d'une classe normale), et lui donne une valeur en suivant la syntaxe indiquée. Notons qu'une énumération ne peut pas être locale (c'est-à-dire déclarée dans une méthode), et qu'elle ne peut pas être anonyme. Déclarer une énumération de cette façon est possible, mais ne permet pas d'utiliser l'énumération Civilite ailleurs que dans la classe où elle est définie. Il est donc possible de déclarer une énumération dans un fichier séparé, comme une classe, en remplaçant simplement le mot-clé class par le mot-clé enum.

Exemple 39. Déclaration d'une énumération

public enum Civilite {  // dans le fichier Civilite.java  
    MADAME, MADEMOISELLE, MONSIEUR  
}

6.2. Classe énumération

Une énumération est en fait une classe, d'où cette appellation de classe énumération. Cette classe étend la classe Enum, qui elle-même étend la classe Object, comme toutes les classes en Java. Les valeurs d'une énumération sont les seules instances possibles de cette classe. Dans notre exemple, Civilite comporte trois instances et trois seulement : MADAME, MADEMOISELLE, MONSIEUR. On peut donc comparer ces instances à l'aide d'un == de façon sûre, même si la comparaison à l'aide de la méthode equals() reste possible.

6.3. Méthode toString()

La méthode toString() de cette classe énumération est surchargée : elle retourne une chaîne de caractères qui porte le nom de la constante considérée. Dans notre exemple :
 System.out.println("Civilite : " + Civilite.MADAME) ;
 -> MADAME

6.4. Méthode valueOf()

La méthode toString() a une méthode symétrique : valueOf(String), qui retourne la valeur énumérée à parir de sa chaîne de caractères. Il existe deux versions de cette méthode, toutes les deux statiques. La première est définie dans la classe énumération Civilite, voyons un exemple de son utilisation.
 Civilite civilite = Civilite.valueOf("MONSIEUR") ;
 -> civilite prend la valeur Civilite.MONSIEUR
La deuxième est définie dans la classe Enum, et prend le nom de l'énumération en paramètre.
 Civilite civilite = Enum.valueOf(Civilite.class, "MONSIEUR") ;
 -> civilite prend la valeur Civilite.MONSIEUR

6.5. Méthode values()

La méthode statique values() retourne un tableau de toutes les valeurs énumérées disponibles.
 Civilite[] civilites = Civilite.values() ;

6.6. Méthode ordinal()

La méthode ordinal() permet de retrouver le numéro d'ordre d'un élément énuméré, dans la liste de tous les éléments d'une énumération. Le premier numéro d'ordre est 0.
 Civilite civilite = Civilite.MADEMOISELLE ;
 System.out.println("Civilite : " + civilite + " [" + civilite.ordinal() + "]") ;
 > Civilite : MADEMOISELLE [1]

6.7. Méthode compareTo()

La méthode compareTo() compare les numéros d'ordre de deux éléments énumérés. Si le premier élément est placé avant le deuxième dans la liste, alors l'entier retourné est négatif, sinon il est positif.
 System.out.println(Civilite.MADAME.compareTo(Civilite.MONSIEUR)) ;
 > -2

6.8. Constructeurs privés

Enfin, il est possible de définir des constructeurs privés pour chacune des valeurs énumérées. Supposons que nous souhaitions associer à chacune de nos valeurs énumérées MADAME, MADEMOISELLE, MONSIEUR, une abréviation : MME, MLLE, MR. Formellement, cela signifie qu'à chaque instance de la classe énumération Civilite, on souhaite associer une propriété, abréviation, qui prend une valeur particulière pour chacune de ces instances. La question est : dans la mesure où nous n'avons vu qu'une façon déclarative de créer une suite de valeurs énumérées, comment initialise-t-on ces instances ? La réponse est apportée par le mécanisme des constructeurs privés. Il est possible, à l'intérieur d'une classe énumération, de définir un unique constructeur par instance, privé, dans lequel on peut procéder à toutes les initialisations que l'on veut. Voyons ceci sur un exemple.

Exemple 40. Énumération : constructeurs privés

public enum Civilite {  // dans le fichier Civilite.java  
  
    MADAME("MME"), MADEMOISELLE("MLLE"), MONSIEUR("MR") ;  
      
     private String abreviation ;  
      
     private Civilite(String abreviation) {  
         this.abreviation = abreviation ;  
    }  
      
     public String getAbreviation() {  
         return  this.abreviation ;  
    }  
}

La création de chacun des éléments énumérés va appeler le constructeur privé, avec la syntaxe donnée lors de la déclaration des éléments énumérés. Ce faisant, le champ abreviation sera correctement initialisé pour chacune des trois instances de notre classe. On peut le constater en exécutant l'exemple suivante.
 Civilite civilite = Civilite.MADEMOISELLE ;
 System.out.println("Civilite : " + civilite + " [" + civilite.getAbreviation() + "]") ;
 > Civilite : MADEMOISELLE [MLLE]
Notons qu'il n'est pas possible de créer des constructeurs non privés dans une classe énumération.

6.9. Classe utilitaire : EnumSet

EnumSet est une classe abstraite fournie dans le but de créer des Set dont les éléments sont des objets énumérés. Elle propose un jeu de méthodes statiques, qui retournent toutes des instances de EnumSet<E>, où E désigne un type énuméré. Par exemple, le code suivant retourne un Set contenant l'ensemble des éléments de l'énumération Civilite.

Exemple 41. Création d'un EnumSet sur une énumération

EnumSet<Civilite> enumSet = EnumSet.allOf(Civilite.class) ;

Java langage & API
Retour au blog Java le soir
Cours & Tutoriaux
Table des matières
Introduction : un peu d'histoire
1. Java : genèse d'un nouveau langage
Programmer en Java
1. Un premier exemple
1.1. Aperçu général, cycle de vie
1.2. Un premier programme
1.3. Programmes, applets, servlets, etc...
2. Une première classe
2.1. Écriture d'une classe
2.2. Instanciation de cette classe
3. Types de base, classes et objets
3.1. Types de base
3.2. Classes et objets
Classes Object et String
1. Introduction
2. La classe Object
2.1. La méthode toString()
2.2. La méthode clone()
2.3. La méthode equals()
2.4. La méthode hashCode()
2.5. La méthode finalize()
2.6. La méthode getClass()
3. La classe String
3.1. Introduction
3.2. Construction d'un objet de type String
3.3. Concaténation, StringBuffer et StringBuilder
3.4. Concaténations de chaînes de caractères depuis Java 8
3.5. Concaténations de chaînes de caractères depuis Java 11
3.6. Extraction d'une sous-chaîne de caractères
3.7. Comparaison de deux chaînes de caractères
3.8. Méthodes de comparaisons lexicographiques
3.9. Méthode de recherche de caractères
3.10. Méthode de modification de chaîne
3.11. Méthode de duplication
3.12. Support de l'unicode, internationalisation
Structure d'une classe
1. Introduction
2. Classes
2.1. Classes publiques
2.2. Classes internes
2.3. Classe membre
2.4. Classes locales
2.5. Classes anonymes
2.6. Le mot-clé this
3. Éléments statiques
3.1. Champ statique
3.2. Cas des constantes
3.3. Bloc statique
3.4. Classe membre statique
4. Membres d'une classe, visibilité
4.1. Bloc non statique
4.2. Accès à un membre, visibilité
4.3. Les champs
4.4. Signature d'une méthode
4.5. Les méthodes
4.6. Getters et Setters
5. Constructeur, instanciation
5.1. Chargement d'une classe
5.2. Constructeurs d'une classe
5.3. Instanciation d'un objet
5.4. Destruction d'objets
5.5. Le mot-clé final
6. Énumérations
6.1. Déclaration d'une énumération
6.2. Classe énumération
6.3. Méthode toString()
6.4. Méthode valueOf()
6.5. Méthode values()
6.6. Méthode ordinal()
6.7. Méthode compareTo()
6.8. Constructeurs privés
6.9. Classe utilitaire : EnumSet
Noms, opérateurs, tableaux
1. Introduction
2. Identificateurs, noms et expressions
2.1. Identificateurs et noms
2.2. Expressions
3. Opérateurs, ordre d'exécution
3.1. Ordre d'exécution
3.2. Les opérateurs
3.3. Les opérateurs ++ et --
3.4. Les opérateurs % et /
3.5. Les opérateurs <<, >> et >>>
3.6. L'opérateur instanceof
3.7. Les opérateurs &, | et ^
3.8. Les opérateurs && et ||
3.9. L'opérateur ? ... :
3.10. Les opérateurs d'affectation
4. Tableaux
4.1. Création d'un tableau
4.2. Initialisation d'un tableau
4.3. Utilisation d'un tableau comme un Object
4.4. Tableaux de tableaux
4.5. Copie de tableaux
5. Blocs, boucles et contrôles
5.1. Blocs
5.2. Mots-clés réservés
5.3. Tests : if et switch
5.4. Boucles : for, while, do ... while
5.5. Commandes continue et break
5.6. Commandes return et goto
Nombres, précision, calculs
1. Introduction
2. Calculs
2.1. Précision
2.2. Codage des nombres flottants
2.3. Le mot-clé strictfp
2.4. Conversion de types
3. Dépassements de capacité
3.1. Cas des entiers
3.2. Cas des flottants
3.3. Bibliothèques BigInteger et BigDecimal
4. Fonctions mathématiques
4.1. Fonctions usuelles
4.2. Générateurs aléatoires
5. Classes enveloppe
5.1. Associer les types de base à des objets
5.2. Auto-boxing
Héritage, abstraction, interfaces
1. Introduction
2. Abstraction et encapsulation
2.1. Abstraction
2.2. Encapsulation
3. Héritage
3.1. Définition de l'héritage
3.2. Conséquences pour les membres
3.3. Polymorphisme
3.4. Empêcher l'héritage
4. Classes abstraites
5. Interfaces
5.1. Introduction
5.2. Définition
5.3. Java 8 et les interfaces
5.4. Utilisation des interfaces
5.5. Définition de constantes dans les interfaces
5.6. Utilité des interfaces
Packages
1. Introduction
2. Notion de paquet
2.1. Déclaration d’appartenance à un paquet
2.2. Chargement d’une classe
2.3. Choix de nom
3. Archives, chemin de recherche, classpath
3.1. Archives
3.2. Variable CLASSPATH
3.3. Notion de classloader
3.4. Bilan sur les classes chargées
3.5. Visibilité
3.6. Conseils d'écriture, bibliothèque standard
Exceptions
1. Introduction
2. Erreurs et Exceptions
2.1. Classe Throwable, notion de stack trace
2.2. Classe Error
2.3. Classe RuntimException
2.4. Classe Exception
3. Déclenchement d'une exception
3.1. Exceptions déclenchées par la JVM
3.2. Exceptions déclenchées par l'application
4. Capter une exception
4.1. Traiter une exception localement
4.2. Code de captage
5. Créer ses propres exceptions
Entrées / sorties
1. Introduction
2. Notion de fichier
2.1. Introduction
2.2. La classe File
2.3. Construction d'une instance de File
2.4. Méthodes exposées
3. Flux de sortie
3.1. Introduction, notion de flux
3.2. Écriture de caractères, classe Writer
3.3. Bufferisation, construction d'un flux sur un autre
3.4. Utilisation de PrintWriter
3.5. Écriture d'octets, OuputStream
3.6. Écriture de types primitifs : DataOutputStream
3.7. Écriture d'objets : ObjectOutputStream
4. Flux d'entrée
4.1. Introduction
4.2. Lecture de caractères, classe Reader
4.3. Bufferisation, lecture ligne par ligne
4.4. Lecture d'octets : InputStream
4.5. Lecture de types primitifs : DataInputStream
4.6. Lecture d'objets : ObjectInputStream
5. Lecture et écriture de flux croisés
5.1. Introduction
5.2. Lire des caractères sur un flux binaire : classe InputStreamReader
5.3. Écrire des caractères sur un flux binaire : classe OutputStreamWriter
5.4. Remarque sur les jeux de caractères
6. Serialization d'objets
6.1. Enjeu de la sérialization d'objets
6.2. Serialization d'un objet
6.3. Sérialization d'une grappe d'objets
6.4. Première surcharge : méthode writeObject() readObject()
6.5. Deuxième surcharge : utilisation d'un externalizer
6.6. Troisième surcharge : utilisation d'un objet proxy
7. Flux compressés
7.1. Introduction
7.2. Flux de type gzip
7.3. Flux de type zip