Astuce Java #6 : Enum et toString

Depuis Java 5, le langage Java dispose d'une nouvelle fonctionnalité : les énumérations.

Les énumérations sont des structures permettant de représenter une variable ayant un nombre fini de valeurs, comme par exemple le sexe d'une personne, qui sera soit "homme", soit "femme".

Les énumérations sont mises en place de la manière suivante :
enum Sex {
    MALE,
    FEMALE;
}

Il est ensuite possible de créer des variables du type de l'énumération, et de les utiliser :
Sex sex = Sex.MALE;
System.out.println(sex);

Et c'est là qu'apparaît notre problème : la console nous affiche "MALE". Certes, il s'agit de la bonne valeur, mais la présentation n'est pas très esthétique. Heureusement pour nous, en Java une énumération est également un objet. Il nous est possible de définir nos propres méthodes, et aussi de récrire certaines méthodes de la classe Object. Ainsi, on peut avoir le code suivant :
enum Sex {
    MALE,
    FEMALE;
    
    @Override
    public String toString() {
        switch (this) {
            case MALE:
                return ("Male");
            case FEMALE:
                return ("Female");
        }
        throw new RuntimeException("Invalid value for this");
    }
}

L'exécution du même code nous donne ainsi "Male" au lieu de "MALE". On obtient le résultat souhaité, à savoir une chaîne de caractères plus facilement lisible par l'utilisateur.

Le soucis que l'on rencontre maintenant viens du switch dans la méthode toString. Nous devons gérer toutes les valeurs possible dans cette méthode, sous peine de lancer une RuntimeException. Une des solutions possibles (que j'ai trouvé dans un commentaire d'un (très) vieux billet de blog), et que je trouve de loin ma préférée, est de fournir un constructeur à notre énumération. Ce constructeur prend en paramètre une chaîne de caractères qui sera utilisée en tant que valeur de retour de la méthode toString :
enum Sex {
    MALE("Male"),
    FEMALE("Female");
    
    private String value;
    
    private Sex(String value) {
        this.value = value;
    }
    
    @Override
    public String toString() {
        return (value);
    }
}

Ainsi, nous obtenons on comportement optimal :
  • Chaque valeur de l'énumération renverra une chaîne de caractères "esthétique" représentant sa valeur
  • Chaque valeur devra posséder une chaîne de caractères (au risque de générer une erreur de compilation)

Le problème majeur qui est ainsi rencontré concerne la conversion énumération -> chaîne de caractères -> énumération. La chaîne de caractères renvoyait de base par toString était le nom de la constante dans l'énumération (MALE ou FEMALE dans notre cas), qui pouvait ensuite être reconverti en énumération via la méthode valueOf. Dans notre cas, la conversion ne se ferra plus puisque toString ne renverra plus une valeur compréhensible par valueOf. Cependant, la méthode name, définie dans toute énumération, renvoie toujours le nom de la constante tel que définit dans le code.

Permalink  |  Commentaires (3)


Comments:

en général on préfère ce genre de syntaxe sans variable intermediaire
enum Sex {
MALE {
@Override
public String toString() {
return "Male";
}
},

FEMALE {
@Override
public String toString() {
return "Female";
}
};

}

Posted by EncoreMieux on juin 20, 2008 at 08:57 PM CEST #

L'inconvénient que certains trouvent à cette approche est la création de classes anonymes en plus de l'énumération en elle même.

Dans le cas d'une énumération comportant n cas, le nombre de classes (énumération + classes anonymes) après compilation est de n+1, ce qui peut rapidement devenir un problème lorsqu'on augmente le nombre de champs dans l'énumération.

Mais il est vrai que ce genre de syntaxe reste couramment utilisé :)

Posted by viv on juin 20, 2008 at 09:14 PM CEST #

Sujet intéressant !
C'est tout de même dommage que 3 ans après la sortie du jdk 5, ce genre de pratique ne reste que très peu utilisée. Pire il reste sous les tirs croisés des deux clans : les antis et les pro-énumerations

Pour allez plus loin sur le sujet, je me permets de vous partager un article que je viens de publier sur le blog de Xebia, vous pourrez y découvrir, comment on passe d'une simple énumération à 3 éléments au 'strategy enum pattern'.

Posted by Erwan ALLIAUME on juillet 23, 2008 at 09:32 PM CEST #

Post a Comment:
  • HTML Syntax: Allowed