Enums

Le type Enum est un des 5 types référence de java (depuis java 5).

Les enums (enumerated types) sont un type spécial de classe, descendant (implicitement) de la classe java.lang.Enum, qui descend elle-même de java.lang.Object.
En créant une enum, on crée un type de donnée qui ne peut prendre qu'un nombre fini de valeurs.

Les enums sont utiles pour spécifier un ensemble de constantes (comme le type enum en sql).

Exemple simple

enum CouleurPrimaire {
    ROUGE,
    VERT,
    BLEU
}

class TestEnum1{
    public static void main(String[] args) {
        System.out.println("Rouge = " + CouleurPrimaire.ROUGE);
        // 
        CouleurPrimaire cp = CouleurPrimaire.ROUGE;
        System.out.println("cp = " + cp);
        
        // la ligne suivante ne passe pas à la compilation
        // if(cp == ROUGE) System.out.println("cp est bien rouge");
        if(cp == CouleurPrimaire.ROUGE) System.out.println("cp est bien rouge");
        
        if(cp.name() == "ROUGE") System.out.println("cp.name() = ROUGE");
        
        switch(cp){
            case ROUGE :
                System.out.println("cp est ROUGE");
            break;  
            case BLEU :
                System.out.println("cp est BLEU");
            break;  
            case VERT :
                System.out.println("cp est VERT");
            break;  

        }
    }
}
(code dans TestEnum1.java)
Cette enum ne peut prendre que 3 valeurs différentes. Les valeurs que peut prendre le type de donnée représenté par l'enum (ROUGE, VERT...) doivent être listées dans le corps de sa classe, obligatoirement au début, et séparées par des virgules.
Remarquer qu'il n'y a aucun modificateur ; sont implicitement public et static.

Au chargement de la classe, les différentes instances sont créées par le compilateur et sont donc accessibles comme des variables statiques (CouleurPrimaire.ROUGE etc.).

Méthode values()

Lorsqu'il crée une enum, le compilateur ajoute automatiquement certaines méthodes, notamment une méthode values(), qu'on peut utiliser dans un foreach :
for(CouleurPrimaire cp : CouleurPrimaire.values()) {
     System.out.println(cp.ordinal() + " " + cp.name() + " " + cp);
}
(code dans TestEnum2.java)
java TestEnum2 
0 ROUGE
1 VERT
2 BLEU

Méthodes héritées de java.lang.Enum

Méthodes d'instance

Le code précédent montre que la méthode toString() renvoie la chaîne de caractère utilisée pour définir l'instance.
Remarquer aussi l'utilisation des méthodes name() et ordinal(), héritées de java.lang.Enum.

name() et toString() renvoient la même chaîne.
ordinal() renvoie un entier exprimant l'ordre de définition des valeurs possibles de l'enum (commence à 0).

Il existe aussi une méthode compareTo(), permettant d'ordonner des enums en utilisant la valeur renvoyée par ordinal().

Méthodes statiques

La méthode Enum.valueOf() permet de créer une instance d'une enum à partir d'une String :
CouleurPrimaire cp = Enum.valueOf(CouleurPrimaire.class, "ROUGE");

Membres d'une enum

Les enums sont des classes, elles peuvent donc avoir des méthodes et des variables.
Si une enum a des membres (variables et / ou méthodes), un point-virgule est obligatoire après la liste des valeurs possibles.
enum CouleurPrimaire {
    
    // liste des valeurs possibles
    
    ROUGE("255 0 0", "FF0000"),
    VERT("0 128 0", "008000"),
    BLEU("0 0 255", "0000FF"); // noter ici le point-virgule
    
    // Définition des champs et méthodes de l'enum
    
    private final String codeRGB;
    
    private final String codeHTML;
    
    private CouleurPrimaire(String codeRGB, String codeHTML){
        this.codeRGB = codeRGB;
        this.codeHTML = codeHTML;
    }
    
    public String getCodeHTML(){ return codeHTML; }
    
    public String getCodeRGB(){ return codeRGB; }
    
}

class TestEnum3{
    
    public static void main(String[] args) {
        for(CouleurPrimaire cp : CouleurPrimaire.values()) {
         System.out.println(cp.ordinal() + "\t" + cp + "\t#" + cp.getCodeHTML() + "\t" + cp.getCodeRGB());
      }
    }
}
(code dans TestEnum3.java)
java TestEnum3
0	ROUGE	#FF0000	255 0 0
1	VERT	#008000	0 128 0
2	BLEU	#0000FF	0 0 255
Noter comment les valeurs des variables d'instance sont spécifiées en même temps que les différentes valeurs que peut prendre l'enum.
    ROUGE("255 0 0", "FF0000"),
On indique que CouleurPrimaire.ROUGE a deux variables d'instance, et que ces deux variables d'instance sont de type String.
Les paramètres passés au constructeur doivent obligatoirement correspondre aux types spécifiés dans la liste des valeurs possibles.

Le constructeur d'une enum doit être de visibilité private ou package.
Exercice : TestArguments
Autre exemple : TestPlanets.java

Pour aller plus loin

Pour la reflection, on dispose des méthodes getEnumConstants() et isEnum() de la classe java.lang.Class.

Voir aussi java.util.EnumSet, qui permet de créer un Set à partir des valeurs d'une enum.
EnumSet<CouleurPrimaire> enumSet = EnumSet.allOf(CouleurPrimaire.class);
Restrictions par rapport à une classe normale :
- Ne peuvent avoir qu'un constructeur private ou de visibilité par défaut.
- Ne peuvent pas être generic.
- Peuvent implementer des interfaces.
- Ne peuvent pas être étendues.