Comment obtenir une valeur enum à partir d'une valeur de chaîne en Java?


Disons que j'ai une énumération qui est juste

public enum Blah {
    A, B, C, D
}

Et je voudrais trouver la valeur enum d'une chaîne, par exemple "A" qui serait Blah.A. Comment serait-il possible de faire cela?

Le Enum.valueOf() est-il la méthode dont j'ai besoin? Si oui, comment pourrais-je utiliser cela?

Author: Steve Chambers, 2009-03-03

24 answers

Oui Blah.valueOf("A") vous donnera Blah.A.

Notez que le nom doit être une correspondance exacte , y compris case: Blah.valueOf("a") et Blah.valueOf("A ") lancent tous deux un IllegalArgumentException.

Les méthodes statiques valueOf() et values() sont créés au moment de la compilation et n'apparaissent pas dans le code source. Ils apparaissent cependant dans Javadoc; par exemple, Dialog.ModalityType affiche les deux méthodes.

 1912
Author: Michael Myers, 2017-09-09 22:26:47

Une autre solution si le texte n'est pas le même que la valeur d'énumération:

public enum Blah {
  A("text1"),
  B("text2"),
  C("text3"),
  D("text4");

  private String text;

  Blah(String text) {
    this.text = text;
  }

  public String getText() {
    return this.text;
  }

  public static Blah fromString(String text) {
    for (Blah b : Blah.values()) {
      if (b.text.equalsIgnoreCase(text)) {
        return b;
      }
    }
    return null;
  }
}
 725
Author: JoséMi, 2017-02-09 12:48:58

Voici un utilitaire astucieux que j'utilise:

/**
 * A common method for all enums since they can't have another base class
 * @param <T> Enum type
 * @param c enum type. All enums must be all caps.
 * @param string case insensitive
 * @return corresponding enum, or null
 */
public static <T extends Enum<T>> T getEnumFromString(Class<T> c, String string) {
    if( c != null && string != null ) {
        try {
            return Enum.valueOf(c, string.trim().toUpperCase());
        } catch(IllegalArgumentException ex) {
        }
    }
    return null;
}

Ensuite, dans ma classe enum, j'ai généralement ceci pour enregistrer une frappe:

public static MyEnum fromString(String name) {
    return getEnumFromString(MyEnum.class, name);
}

Si vos énumérations ne sont pas toutes en majuscules, changez simplement la ligne Enum.valueOf.

Dommage que je ne puisse pas utiliser T.class pour Enum.valueOf car T est effacé.

 101
Author: Geoffrey Zheng, 2014-11-17 20:23:38

Vous devriez également être prudent avec votre cas. Permettez-moi d'expliquer: faire Blah.valueOf("A") fonctionne, mais Blah.valueOf("a") ne fonctionnera pas. Là encore Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) fonctionnerait.

Modifier
Changé toUpperCase en toUpperCase(Locale.ENGLISH)basé sur tc. comment et les documents java

Edit2 Sur android, vous devez utiliser Locale.US, comme sulai souligne.

 66
Author: João Portela, 2017-05-23 12:26:38

Utilisez le modèle de Joshua Bloch, Java efficace :

(simplifié pour plus de concision)

enum MyEnum {
  ENUM_1("A"),
  ENUM_2("B");

  private String name;

  private static final Map<String,MyEnum> ENUM_MAP;

  MyEnum (String name) {
    this.name = name;
  }

  public String getName() {
    return this.name;
  }

  // Build an immutable map of String name to enum pairs.
  // Any Map impl can be used.

  static {
    Map<String,MyEnum> map = new ConcurrentHashMap<String,MyEnum>();
    for (MyEnum instance : MyEnum.values()) {
      map.put(instance.getName(),instance);
    }
    ENUM_MAP = Collections.unmodifiableMap(map);
  }

  public static MyEnum get (String name) {
    return ENUM_MAP.get(name);
  }
}

Voir Aussi:

Exemple Java Oracle utilisant l'énumération et la carte des instances

Ordre d'Exécution des blocs statiques dans un type Enum

Comment puis-je rechercher une énumération Java à partir de sa valeur de chaîne

 40
Author: Darrell Teague, 2017-05-23 12:34:45

Voici une méthode qui peut le faire pour n'importe quelle énumération, et qui est insensible à la casse.

/** 
 * Finds the value of the given enumeration by name, case-insensitive. 
 * Throws an IllegalArgumentException if no match is found.  
 **/
public static <T extends Enum<T>> T valueOfIgnoreCase(
        Class<T> enumeration, String name) {

    for (T enumValue : enumeration.getEnumConstants()) {
        if (enumValue.name().equalsIgnoreCase(name)) {
            return enumValue;
        }
    }

    throw new IllegalArgumentException(String.format(
        "There is no value with name '%s' in Enum %s",
        name, enumeration.getName()
    ));
}
 34
Author: Patrick Arnesen, 2015-04-22 21:22:37

L'utilisation de Blah.valueOf(string) est préférable mais vous pouvez également utiliser Enum.valueOf(Blah.class, string).

 28
Author: Peter Lawrey, 2013-08-12 01:13:19

Si vous ne voulez pas écrire votre propre utilitaire de Google goyave bibliothèque:

Enums.getIfPresent(Blah.class, "A")

Contrairement à la fonction java intégrée, il vous permet de vérifier si A est présent dans Blah et ne lève pas d'exception.

 24
Author: Andrejs, 2014-04-02 20:12:18

Vous devrez peut-être ceci :

public enum ObjectType {
    PERSON("Person");

    public String parameterName;

    ObjectType(String parameterName) {
        this.parameterName = parameterName;
    }

    public String getParameterName() {
        return this.parameterName;
    }

    //From String method will return you the Enum for the provided input string
    public static ObjectType fromString(String parameterName) {
        if (parameterName != null) {
            for (ObjectType objType : ObjectType.values()) {
                if (parameterName.equalsIgnoreCase(objType.parameterName)) {
                    return objType;
                }
            }
        }
        return null;
    }
}

Une Autre addition:

   public static String fromEnumName(String parameterName) {
        if (parameterName != null) {
            for (DQJ objType : DQJ.values()) {
                if (parameterName.equalsIgnoreCase(objType.name())) {
                    return objType.parameterName;
                }
            }
        }
        return null;
    }

Cela vous retournera la Valeur par un nom d'énumération Stringifié Car, par exemple, si vous fournissez "PERSON "dans le fromEnumName, il vous retournera la Valeur de Enum, c'est-à-dire"Person"

 13
Author: Murtaza Kanchwala, 2015-10-29 14:38:55

En Java 8 ou version ultérieure, en utilisant Streams :

public enum Blah
{
    A("text1"),
    B("text2"),
    C("text3"),
    D("text4");

    private String text;

    Blah(String text) {
        this.text = text;
    }

    public String getText() {
        return this.text;
    }

    public static Blah fromText(String text) {
        return Arrays.stream(values())
          .filter(bl -> bl.text.equalsIgnoreCase(text))
          .findFirst()
          .orElse(null);
    }
}
 11
Author: Hans Schreuder, 2018-04-10 05:23:39

Mes 2 cents ici: utilisation de flux Java8 + vérification d'une chaîne exacte:

public enum MyEnum {
    VALUE_1("Super"),
    VALUE_2("Rainbow"),
    VALUE_3("Dash"),
    VALUE_3("Rocks");

    private final String value;

    MyEnum(String value) {
        this.value = value;
    }

    /**
     * @return the Enum representation for the given string.
     * @throws IllegalArgumentException if unknown string.
     */
    public static MyEnum fromString(String s) throws IllegalArgumentException {
        return Arrays.stream(MyEnum.values())
                .filter(v -> v.value.equals(s))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("unknown value: " + s));
    }
}

* * MODIFIER * *

A renommé la fonction en fromString() depuis qu'elle a été nommée en utilisant cette convention, vous obtiendrez certains avantages du langage Java lui-même; par exemple:

  1. Conversion directe des types à l'annotation HeaderParam
 11
Author: Manu, 2018-08-02 20:56:37

Une autre façon de le faire en utilisant la méthode statique implicite name() d'Enum. name retournera la chaîne exacte utilisée pour créer cette énumération qui peut être utilisée pour vérifier la chaîne fournie:

public enum Blah {

    A, B, C, D;

    public static Blah getEnum(String s){
        if(A.name().equals(s)){
            return A;
        }else if(B.name().equals(s)){
            return B;
        }else if(C.name().equals(s)){
            return C;
        }else if (D.name().equals(s)){
            return D;
        }
        throw new IllegalArgumentException("No Enum specified for this string");
    }
}

Test:

System.out.println(Blah.getEnum("B").name());

//it will print B  B

Inspiration: 10 Exemples d'énumération en Java

 10
Author: Vikram, 2011-11-29 05:48:52

Solution utilisant les bibliothèques de Goyave. La méthode getPlanet () est insensible à la casse, donc getPlanet ("MerCUrE") retournera Planète.MERCURE.

package com.universe.solarsystem.planets;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Enums;
import com.google.common.base.Optional;

//Pluto and Eris are dwarf planets, who cares!
public enum Planet {
   MERCURY,
   VENUS,
   EARTH,
   MARS,
   JUPITER,
   SATURN,
   URANUS,
   NEPTUNE;

   public static Planet getPlanet(String name) {
      String val = StringUtils.trimToEmpty(name).toUpperCase();
      Optional <Planet> possible = Enums.getIfPresent(Planet.class, val);
      if (!possible.isPresent()) {
         throw new IllegalArgumentException(val + "? There is no such planet!");
      }
      return possible.get();
   }
}
 6
Author: javabrew, 2014-08-23 02:02:09

Pour ajouter aux réponses précédentes et aborder certaines des discussions autour des nulls et des NPE, j'utilise des options de goyave pour gérer les cas absents/invalides. Cela fonctionne très bien pour l'analyse URI/paramètre.

public enum E {
    A,B,C;
    public static Optional<E> fromString(String s) {
        try {
            return Optional.of(E.valueOf(s.toUpperCase()));
        } catch (IllegalArgumentException|NullPointerException e) {
            return Optional.absent();
        }
    }
}

Pour ceux qui ne le savent pas, voici quelques informations supplémentaires sur l'évitement de null avec Optionnel: https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional

 6
Author: tom, 2015-04-22 21:56:49
public static MyEnum getFromValue(String value) {
    MyEnum resp = null;
    MyEnum nodes[] = values();
    for(int i = 0; i < nodes.length; i++) {
        if(nodes[i].value.equals(value)) {
            resp = nodes[i];
            break;
        }
    }
    return resp;
}
 5
Author: Prasobh.K, 2015-04-22 21:50:50

O(1) méthode inspirée du code généré par thrift qui utilise un hashmap.

public enum USER {
        STUDENT("jon",0),TEACHER("tom",1);

        private static final Map<String, Integer> map = new HashMap<>();

        static {
                for (USER user : EnumSet.allOf(USER.class)) {
                        map.put(user.getTypeName(), user.getIndex());
                }
        }

        public static int findIndexByTypeName(String typeName) {
                return map.get(typeName);
        }

        private USER(String typeName,int index){
                this.typeName = typeName;
                this.index = index;
        }
        private String typeName;
        private int index;
        public String getTypeName() {
                return typeName;
        }
        public void setTypeName(String typeName) {
                this.typeName = typeName;
        }
        public int getIndex() {
                return index;
        }
        public void setIndex(int index) {
                this.index = index;
        }

}
 4
Author: Sisyphus, 2015-09-23 09:08:33

En Java 8, le modèle de carte statique est encore plus facile et est ma méthode préférée. Si vous voulez utiliser l'énumération avec Jackson, vous pouvez remplacer toString et l'utiliser au lieu de name, puis annoter avec @JsonValue

public enum MyEnum {
    BAR,
    BAZ;
    private static final Map<String, MyEnum> MAP = Stream.of(MyEnum.values()).collect(Collectors.toMap(Enum::name, Function.identity()));
    public static MyEnum fromName(String name){
        return MAP.get(name);
    }
}

public enum MyEnumForJson {
    BAR("bar"),
    BAZ("baz");
    private static final Map<String, MyEnumForJson> MAP = Stream.of(MyEnumForJson.values()).collect(Collectors.toMap(Object::toString, Function.identity()));
    private final String value;

    MyEnumForJson(String value) {
        this.value = value;
    }

    @JsonValue
    @Override
    public String toString() {
        return value;
    }

    public static MyEnumForJson fromValue(String value){
        return MAP.get(value);
    }
}
 4
Author: Novaterata, 2017-04-27 17:10:02

java.lang.Enum définit plusieurs méthodes utiles, disponibles pour tous les types d'énumération en Java:

  • Vous pouvez utiliser la méthode name() pour obtenir le nom de toutes les constantes Enum. Le littéral de chaîne utilisé pour écrire des constantes enum est leur nom.
  • De même, la méthode values() peut être utilisée pour obtenir un tableau de toutes les constantes Enum à partir d'un type Enum.
  • Et pour la question posée, vous pouvez utiliser la méthode valueOf() pour convertir n'importe quelle chaîne en constante Enum en Java, comme indiqué ci-dessous.
public class EnumDemo06 {
    public static void main(String args[]) {
        Gender fromString = Gender.valueOf("MALE");
        System.out.println("Gender.MALE.name() : " + fromString.name());
    }

    private enum Gender {
        MALE, FEMALE;
    }
}

Output:
Gender.MALE.name() : MALE

Dans cet extrait de code, valueOf() méthode renvoie un genre constant Enum.Mâle, nom d'appel sur ce retour "MALE".

 3
Author: KNU, 2015-04-22 21:54:41

Le commons-lang bibliothèque a une fonction statique org.Apache.commun.lang3.EnumUtils.getEnum qui mappera une chaîne à votre type d'énumération. Même réponse essentiellement que Geoffreys mais pourquoi rouler le vôtre quand il est déjà dans la nature.

 2
Author: pjklauser, 2015-10-22 06:46:11

Ajout à la réponse la mieux notée, avec un utilitaire utile...

valueOf() lève deux exceptions différentes dans les cas où il n'aime pas son entrée.

  • IllegalArgumentException
  • NullPointerExeption

Si vos exigences sont telles que vous n'avez aucune garantie que votre chaîne correspondra certainement à une valeur enum, par exemple si les données de chaîne proviennent d'une base de données et peuvent contenir une ancienne version de l'enum, vous devrez les gérer souvent...

Voici donc un méthode réutilisable que j'ai écrite qui nous permet de définir une énumération par défaut à renvoyer si la chaîne que nous passons ne correspond pas.

private static <T extends Enum<T>> T valueOf( String name , T defaultVal) {
        try {
            return Enum.valueOf(defaultVal.getDeclaringClass() , name);
        } catch (IllegalArgumentException | NullPointerException e) {
            return defaultVal;
        }
    }

Utilisez-le comme ceci:

public enum MYTHINGS {
    THINGONE,
    THINGTWO
}

public static void main(String [] asd) {
  valueOf("THINGTWO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGTWO
  valueOf("THINGZERO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGONE
}
 2
Author: lance.dolan, 2017-07-11 17:01:56

Un autre utilitaire capturant de manière inverse. En utilisant une valeur qui identifie cette énumération, pas à partir de son nom.

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.EnumSet;

public class EnumUtil {

    /**
     * Returns the <code>Enum</code> of type <code>enumType</code> whose a 
     * public method return value of this Enum is 
     * equal to <code>valor</code>.<br/>
     * Such method should be unique public, not final and static method 
     * declared in Enum.
     * In case of more than one method in match those conditions
     * its first one will be chosen.
     * 
     * @param enumType
     * @param value
     * @return 
     */
    public static <E extends Enum<E>> E from(Class<E> enumType, Object value) {
        String methodName = getMethodIdentifier(enumType);
        return from(enumType, value, methodName);
    }

    /**
     * Returns the <code>Enum</code> of type <code>enumType</code> whose  
     * public method <code>methodName</code> return is 
     * equal to <code>value</code>.<br/>
     *
     * @param enumType
     * @param value
     * @param methodName
     * @return
     */
    public static <E extends Enum<E>> E from(Class<E> enumType, Object value, String methodName) {
        EnumSet<E> enumSet = EnumSet.allOf(enumType);
        for (E en : enumSet) {
            try {
                String invoke = enumType.getMethod(methodName).invoke(en).toString();
                if (invoke.equals(value.toString())) {
                    return en;
                }
            } catch (Exception e) {
                return null;
            }
        }
        return null;
    }

    private static String getMethodIdentifier(Class<?> enumType) {
        Method[] methods = enumType.getDeclaredMethods();
        String name = null;
        for (Method method : methods) {
            int mod = method.getModifiers();
            if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && !Modifier.isFinal(mod)) {
                name = method.getName();
                break;
            }
        }
        return name;
    }
}

Exemple:

public enum Foo {
    ONE("eins"), TWO("zwei"), THREE("drei");

    private String value;

    private Foo(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

EnumUtil.from(Foo.class, "drei") renvoie Foo.THREE, car il utilisera getValue pour correspondre à "drei", qui est une méthode publique unique, non finale et non statique dans Foo. Dans le cas où Foo a plus que sur la méthode publique, non finale et non statique, par exemple, getTranslate qui renvoie "drei", l'autre méthode peut être utilisée: EnumUtil.from(Foo.class, "drei", "getTranslate").

 1
Author: Moesio, 2016-02-24 11:39:28

Qu'en est-il?

public enum MyEnum {
    FIRST,
    SECOND,
    THIRD;

    public static Optional<MyEnum> fromString(String value){
        try{
            return Optional.of(MyEnum.valueOf(value));
        }catch(Exception e){
            return Optional.empty();
        }
    }
}
 1
Author: D.C., 2017-12-30 07:38:31

En tant que switch-version n'a pas encore été mentionnée je l'introduit (réutilisant l'énumération d'OP):

  private enum Blah {
    A, B, C, D;

    public static Blah byName(String name) {
      switch (name) {
        case "A":
          return A;
        case "B":
          return B;
        case "C":
          return C;
        case "D":
          return D;
        default:
          throw new IllegalArgumentException(
            "No enum constant " + Blah.class.getCanonicalName() + "." + name);
      }
    }
  }

Puisque cela ne donne aucune valeur supplémentaire à la méthode valueOf(String name), il n'est logique de définir une méthode supplémentaire que si nous voulons avoir un comportement différent. Si nous ne voulons pas lever un IllegalArgumentException, nous pouvons changer l'implémentation en:

  private enum Blah {
    A, B, C, D;

    public static Blah valueOfOrDefault(String name, Blah defaultValue) {
      switch (name) {
        case "A":
          return A;
        case "B":
          return B;
        case "C":
          return C;
        case "D":
          return D;
        default:
          if (defaultValue == null) {
            throw new NullPointerException();
          }
          return defaultValue;
      }
    }
  }

En fournissant une valeur par défaut, nous conservons le contrat de Enum.valueOf(String name) sans lancer un IllegalArgumentException de cette manière qu'en aucun cas null n'est retourner. Par conséquent, nous jeter un NullPointerException si le nom est null et dans le cas de default si defaultValue est null. C'est ainsi que valueOfOrDefault fonctionne.

Cette approche adopte la conception de l'interface Map qui fournit une méthode Map.getOrDefault(Object key, V defaultValue) à partir de Java 8.

 1
Author: LuCio, 2018-08-02 21:19:58

J'aime utiliser ce genre de processus pour analyser les commandes sous forme de chaînes dans les énumérations. J'ai normalement l'une des énumérations comme "inconnue", il est donc utile de l'avoir renvoyée lorsque les autres ne sont pas trouvées (même insensibles à la casse) plutôt que null (ce qui signifie qu'il n'y a pas de valeur). Par conséquent, j'utilise cette approche.

static <E extends Enum<E>> Enum getEnumValue(String what, Class<E> enumClass) {
    Enum<E> unknown=null;
    for (Enum<E> enumVal: enumClass.getEnumConstants()) {  
        if (what.compareToIgnoreCase(enumVal.name()) == 0) {
            return enumVal;
        }
        if (enumVal.name().compareToIgnoreCase("unknown") == 0) {
            unknown=enumVal;
        }
    }  
    return unknown;
}
 0
Author: John Hemming, 2016-08-30 09:11:58