Comment obtenir une valeur enum à partir d'une valeur string en Java?

Dire que j'ai un enum 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?

est-ce que le Enum.valueOf() est la méthode dont j'ai besoin? Dans l'affirmative, comment puis-je m'en servir?

1643
demandé sur Steve Chambers 2009-03-03 01:56:34

24 réponses

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

notez que le nom doit être un exact match, y compris le cas: Blah.valueOf("a") et Blah.valueOf("A ") les deux jeter un IllegalArgumentException .

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

1912
répondu 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
répondu 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;
}

alors dans ma classe d'enum j'ai habituellement ceci pour sauver quelques dactylographier:

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

si vos enums ne sont pas tous des capuchons, changez simplement la ligne Enum.valueOf .

dommage que je ne puisse pas utiliser T.class pour Enum.valueOf comme T est effacé.

101
répondu Geoffrey Zheng 2014-11-17 20:23:38

vous devriez également être prudent avec votre cas. Laissez-moi vous expliquer: faire Blah.valueOf("A") fonctionne, mais Blah.valueOf("a") ne fonctionnera pas. Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) fonctionnerait.

modifier

Modifié toUpperCase en toUpperCase(Locale.ENGLISH) basé sur tc. commentaire et le java docs

edit2 Sur android, vous devez utiliser Locale.US , sulai points .

66
répondu João Portela 2017-05-23 12:26:38

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

(simplifié par 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:

Oracle Exemple Java à l'aide de l'Enum et Carte des instances

ordre d'exécution de blocs statiques de type Enum

Comment puis-je chercher un Java enum à partir de sa chaîne valeur

40
répondu Darrell Teague 2017-05-23 12:34:45

Voici une méthode qui peut le faire pour n'importe quel Énum, et 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
répondu Patrick Arnesen 2015-04-22 21:22:37

utiliser Blah.valueOf(string) est préférable, mais vous pouvez utiliser Enum.valueOf(Blah.class, string) ainsi.

28
répondu Peter Lawrey 2013-08-12 01:13:19

vous pourriez avoir besoin de 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;
    }
}

Un Ajout De Plus:

   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 Enum Stringifié pour par exemple si vous fournissez "personne" dans le nom de fromenum il vous rendra la valeur D'Enum i.e." personne "

13
répondu Murtaza Kanchwala 2015-10-29 14:38:55

en Java 8 ou plus tard, 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
répondu Hans Schreuder 2018-04-10 05:23:39

mes 2 cents ici: en utilisant Java8 Streams + 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));
    }
}

* * EDIT * *

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

  1. conversion directe des types à la rubrique annotation
11
répondu Manu 2018-08-02 20:56:37

une autre façon de le faire en utilisant la méthode statique implicite name() de L'Enum. nom retournera la chaîne exacte utilisée pour créer cet enum qui peut être utilisé 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'Enum en Java

10
répondu Vikram 2011-11-29 05:48:52

Solution utilisant des bibliothèques de goyaves. 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
répondu javabrew 2014-08-23 02:02:09

pour ajouter aux réponses précédentes, et répondre à certaines des discussions autour nulls et NPE j'utilise des options de goyave pour traiter les cas absents/invalides. Cela fonctionne très bien pour URI/parameter parsing.

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 plus d'informations sur la façon d'éviter null avec option: https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional

6
répondu 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
répondu Prasobh.K 2015-04-22 21:50:50

O(1) méthode inspirée de l'épargne code généré qui utilisent une table de hachage.

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
répondu 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éferée. Si vous voulez utiliser L'Enum avec Jackson vous pouvez outrepasser toString et utiliser cela à la place du nom, 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
répondu Novaterata 2017-04-27 17:10:02

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

  • vous pouvez utiliser la méthode name() pour obtenir le nom de n'importe quelles constantes Enum. String literal utilisé pour écrire les constantes d'enum est leur nom.
  • de la même manière values() méthode 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 de caractères 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 ce code snippet, valueOf() méthode retourne un genre constant Enum.Homme, appelant nom sur qui renvoie "MALE" .

3
répondu KNU 2015-04-22 21:54:41

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

2
répondu pjklauser 2015-10-22 06:46:11

ajoute à la réponse la mieux cotée, avec un utilitaire utile...

valueOf() Lance 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 de caractères correspondra définitivement à une valeur enum, par exemple si les données de la chaîne proviennent d'une base de données et pourrait contenir une ancienne version de l'enum, alors vous aurez besoin de gérer ces souvent...

voici donc une méthode réutilisable que j'ai écrite qui nous permet de définir un Enum par défaut à retourner 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
répondu lance.dolan 2017-07-11 17:01:56

un autre utilitaire capturant en sens inverse. En utilisant une valeur qui identifie cet Enum, 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") returns Foo.THREE , parce qu'il va utiliser getValue pour correspondre à "drei", qui est public unique, Pas finale et pas méthode statique dans Foo. Dans le cas de Foo a plus que sur la méthode publique, Pas finale et non statique, par exemple, getTranslate qui renvoie" drei", l'autre méthode peut être utilisé: EnumUtil.from(Foo.class, "drei", "getTranslate") .

1
répondu Moesio 2016-02-24 11:39:28

à quel sujet?

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
répondu D.C. 2017-12-30 07:38:31

comme une switch - la version n'a pas été mentionnée mais je l'introduis (réutilisant OP's enum):

  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) , cela n'a de sens que de définir une méthode supplémentaire si nous voulons avoir un comportement différent. Si nous ne voulons pas soulever un IllegalArgumentException nous pouvons changer la mise en œuvre à:

  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 telle manière qu'en aucun cas null ne soit retourné. Par conséquent, nous lançons un NullPointerException si le nom est null et dans le cas de default si defaultValue est null . C'est comme ça que valueOfOrDefault fonctionne.

cette approche adopte la conception de Map - Interface qui fournit une méthode Map.getOrDefault(Object key, V defaultValue) à partir de Java 8.

1
répondu LuCio 2018-08-02 21:19:58

j'aime utiliser ce genre de processus pour analyser les commandes comme des chaînes dans des énumérations. J'ai normalement une des énumérations comme "inconnue" de sorte qu'il est utile d'avoir ce retour lorsque les autres ne sont pas trouvés (même sur une base insensible de cas) plutôt que nul (ce qui signifie qu'il n'y a aucune valeur). J'ai donc utiliser 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
répondu John Hemming 2016-08-30 09:11:58