Obtenir une valeur d'enum à partir d'une chaîne en Java

Convertir une chaîne en valeur d'enum est une opération courante : lecture de paramètres, parsing JSON, configuration. Java fournit la méthode valueOf() intégrée, mais son comportement strict piège souvent les développeurs.

La méthode valueOf() générée par le compilateur

Tout enum Java hérite d'une méthode valueOf(String) statique, générée automatiquement :

public enum Jour {
    LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE
}

Jour j = Jour.valueOf("LUNDI");
System.out.println(j); // LUNDI

La correspondance doit être exacte, casse comprise. "lundi" ou "Lundi" lèvent IllegalArgumentException.

Gérer le cas où la chaîne est invalide

try {
    Jour j = Jour.valueOf("Dimanche");
} catch (IllegalArgumentException e) {
    System.out.println("Jour inconnu");
} catch (NullPointerException e) {
    System.out.println("Chaîne null");
}

Deux exceptions à prévoir : IllegalArgumentException si le nom n'existe pas, NullPointerException si la chaîne est null.

Version tolérante à la casse

Pour accepter n'importe quelle casse, ajoutez une méthode fromString à l'enum :

public enum Jour {
    LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE;

    public static Jour fromString(String s) {
        if (s == null) return null;
        return Jour.valueOf(s.trim().toUpperCase());
    }
}

Version qui retourne Optional

Plutôt qu'une exception, renvoyez un Optional vide :

public static Optional<Jour> fromStringOptional(String s) {
    if (s == null) return Optional.empty();
    try {
        return Optional.of(Jour.valueOf(s.trim().toUpperCase()));
    } catch (IllegalArgumentException e) {
        return Optional.empty();
    }
}

// Utilisation
Jour j = Jour.fromStringOptional("lundi").orElse(Jour.LUNDI);

Faire correspondre un libellé différent du nom de constante

Souvent, on veut stocker en base un libellé plus lisible que LUNDI, ou supporter plusieurs alias. Attribuez un libellé à chaque constante :

public enum Jour {
    LUNDI("lun"), MARDI("mar"), MERCREDI("mer"),
    JEUDI("jeu"), VENDREDI("ven"), SAMEDI("sam"), DIMANCHE("dim");

    private final String libelle;

    Jour(String libelle) { this.libelle = libelle; }

    public String libelle() { return libelle; }

    public static Jour fromLibelle(String libelle) {
        for (Jour j : values()) {
            if (j.libelle.equalsIgnoreCase(libelle)) return j;
        }
        throw new IllegalArgumentException("Libellé inconnu : " + libelle);
    }
}

Jour.fromLibelle("ven"); // VENDREDI

Cache pour de meilleures performances

Si l'enum a beaucoup de valeurs et que la conversion est fréquente (parsing de milliers de lignes), utilisez une Map préconstruite :

public enum Jour {
    LUNDI("lun"), MARDI("mar"); /* … */

    private static final Map<String, Jour> INDEX = Arrays.stream(values())
        .collect(Collectors.toMap(j -> j.libelle.toLowerCase(), j -> j));

    public static Jour fromLibelle(String libelle) {
        Jour j = INDEX.get(libelle == null ? null : libelle.toLowerCase());
        if (j == null) throw new IllegalArgumentException("Libellé inconnu : " + libelle);
        return j;
    }
}

Recherche en O(1) au lieu de O(n) sur un scan linéaire.

Parsing JSON

Avec Jackson, la désérialisation utilise valueOf par défaut — donc casse sensible. Pour la rendre tolérante :

ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);
mapper.configure(DeserializationFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true);

Ou annotez une méthode avec @JsonCreator :

public enum Statut {
    ACTIF, INACTIF;

    @JsonCreator
    public static Statut fromJson(String s) {
        return Statut.valueOf(s.toUpperCase());
    }
}

values() — obtenir toutes les valeurs

for (Jour j : Jour.values()) {
    System.out.println(j + " = " + j.ordinal());
}

Attention : values() crée un nouveau tableau à chaque appel. Cachez-le si vous itérez souvent.

Récapitulatif

BesoinSolution
Conversion stricteJour.valueOf("LUNDI")
Insensible à la cassevalueOf(s.toUpperCase())
Sans exceptionméthode fromString + Optional
Libellé différentchamp + méthode fromLibelle
Grand volumecache statique en Map
JSONJackson + @JsonCreator

La meilleure pratique : toujours exposer une méthode fromString explicite dans l'enum plutôt que de laisser les appelants composer avec valueOf et les exceptions.