如何从Java中的字符串值获取枚举值?

时间:2009-03-02 22:56:35

标签: java enums

说我有一个只是

的枚举
public enum Blah {
    A, B, C, D
}

我希望找到一个字符串的枚举值,例如"A",它将是Blah.A。怎么可能这样做?

我需要Enum.valueOf()方法吗?如果是这样,我将如何使用它?

30 个答案:

答案 0 :(得分:2071)

是的,Blah.valueOf("A")将为您提供Blah.A

请注意,该名称必须是完全匹配,包括案例:Blah.valueOf("a")Blah.valueOf("A ")都会抛出IllegalArgumentException

静态方法valueOf()values()是在编译时创建的,不会出现在源代码中。但它们确实出现在Javadoc中;例如,Dialog.ModalityType显示两种方法。

答案 1 :(得分:791)

如果文本与枚举值不同,则为另一种解决方案:

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;
    }
}

答案 2 :(得分:111)

这是我使用的一个漂亮的实用程序:

/**
 * 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;
}

然后在我的枚举课中,我通常会这样做以节省一些打字:

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

如果您的枚举不是全部大写,只需更改Enum.valueOf行。

太糟糕了我无法将T.class用于Enum.valueOf,因为T已被删除。

答案 3 :(得分:72)

你也应该小心你的情况。让我解释一下:做Blah.valueOf("A")有效,但Blah.valueOf("a")无效。然后Blah.valueOf("a".toUpperCase(Locale.ENGLISH))再次起作用。

修改
根据{{​​3}}和tc. comment

toUpperCase更改为toUpperCase(Locale.ENGLISH)

<强> EDIT2 在Android上,您应该使用java docsLocale.US

答案 4 :(得分:65)

使用Joshua Bloch的模式, Effective Java

(为简洁而简化)

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);
    }
}

另见:

Oracle Java Example using Enum and Map of instances

Execution order of of static blocks in an Enum type

How can I lookup a Java enum from its String value

答案 5 :(得分:36)

这是一个可以为任何枚举执行此操作的方法,并且不区分大小写。

/** 
 * 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()
    ));
}

答案 6 :(得分:31)

最好使用Blah.valueOf(string),但您也可以使用Enum.valueOf(Blah.class, string)

答案 7 :(得分:26)

如果您不想编写自己的实用程序,请使用Google的库:

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

与内置的java函数不同,它让你检查Blah中是否存在A并且不会抛出异常。

答案 8 :(得分:22)

我的2美分:使用Java8 Streams +检查确切的字符串:

fromString()

**编辑**

将函数重命名为.replace("\t", ""),因为使用该约定命名它,您将从Java语言本身获得一些好处;例如:

  1. Direct conversion of types at HeaderParam annotation

答案 9 :(得分:19)

在Java 8或更高版本中,使用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 Optional<Blah> fromText(String text) {
        return Arrays.stream(values())
          .filter(bl -> bl.text.equalsIgnoreCase(text))
          .findFirst();
    }
}

答案 10 :(得分:14)

您可能需要这样:

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;
    }
}

再增加一次:

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

这将通过字符串化的枚举名称返回值,例如如果您提供&#34; PERSON&#34;在fromEnumName中,它会返回Enum的值,即&#34; Person&#34;

答案 11 :(得分:11)

使用Enum的隐式静态方法name()执行此操作的另一种方法。 name将返回用于创建该枚举的确切字符串,该字符串可用于检查提供的字符串:

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");
    }
}

测试:

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

//it will print B  B

灵感:10 Examples of Enum in Java

答案 12 :(得分:7)

使用Guava库的解决方案。方法getPlanet()不区分大小写,所以 getPlanet(“MerCUrY”)将返回Planet.MERCURY。

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();
   }
}

答案 13 :(得分:6)

要添加到先前的答案,并解决围绕null和NPE的一些讨论我正在使用Guava Optionals来处理缺席/无效案例。这适用于URI /参数解析。

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();
        }
    }
}

对于那些不知道的人,这里有一些关于使用Optional https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional

避免null的更多信息

答案 14 :(得分:6)

在Java 8中,静态Map模式更加简单,是我的优先方法。如果你想使用Enum with Jackson,你可以覆盖toString并使用它而不是名字,然后使用@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);
    }
}

答案 15 :(得分:5)

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;
}

答案 16 :(得分:4)

O(1)方法受益于使用散列映射的thrift生成的代码。

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;
        }

}

答案 17 :(得分:3)

java.lang.Enum定义了几种有用的方法,可用于Java中的所有枚举类型:

  • 您可以使用name()方法获取任何枚举常量的名称。用于编写枚举常量的字符串文字是它们的名称。
  • 类似地,values()方法可用于从Enum类型获取所有枚举常量的数组。
  • 对于提出的问题,您可以使用valueOf()方法将任何String转换为Java中的Enum常量,如下所示。
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

在此代码段中,valueOf()方法返回枚举常量Gender.MALE,调用name返回"MALE"

答案 18 :(得分:3)

Apache的commons-lang库有一个静态函数org.apache.commons.lang3.EnumUtils.getEnum,它将String映射到您的Enum类型。基本上和Geoffreys一样的答案,但是为什么在野外已经存在的情况下推出自己的答案。

答案 19 :(得分:3)

使用实用的实用程序添加到评分最高的答案...

valueOf()会在不喜欢输入的情况下抛出两个不同的异常。

  • IllegalArgumentException
  • NullPointerExeption

如果您的要求使您无​​法保证您的String肯定会与枚举值匹配,例如,如果String数据来自数据库并且可能包含旧版本的枚举,那么您将需要经常处理这些...

所以这里是我编写的一个可重用的方法,它允许我们定义一个默认的Enum,如果我们传递的String不匹配则返回。

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;
        }
    }

像这样使用:

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
}

答案 20 :(得分:2)

怎么样?

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();
        }
    }
}

答案 21 :(得分:1)

另一种以相反方式捕获的实用程序。使用标识该枚举的值,而不是其名称。

$fields = get_field_objects();


if ( !empty($fields) ){
    echo "<dl class='clearfix'>";
    foreach ( $fields as $field ){
       if (empty($field['value']))  continue;
       echo "<dt>".$field['label']."</dt><dd>".$field['value']."</dd>";
       echo '<br class="clear">';
    }
    echo "</dl>";
}

示例:

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;
    }
}

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"),因为它会使用Foo.THREE来匹配&#34; drei&#34;,这是唯一的公共,而不是Foo中的最终和非静态方法。 如果Foo不仅仅是公共的,而不是最终的而非静态的方法,例如getValue返回&#34; drei&#34;,可以使用另一种方法:getTranslate

答案 22 :(得分:1)

枚举 valueOf() 枚举类在编译时会自动获取类中的静态 valueOf() 方法。 valueOf() 方法可用于获取给定 String 值的枚举类的实例。 例如:-

public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println(Strings.TWO.name());
    }
    enum Strings {
        ONE, TWO, THREE
    }
}

答案 23 :(得分:1)

我正在寻找一个答案来找到“废话”名称而不是它的值(不是文本)。基于@Manu (@Mano)answer 我发现此代码很有用:

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 valueOfCode(String blahCode) throws IllegalArgumentException {
    Blah blah = Arrays.stream(Blah.values())
            .filter(val -> val.name().equals(blahCode))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("Unable to resolve blah : " + blahCode));

    return blah;
}

}

答案 24 :(得分:1)

枚举非常有用,我经常使用Enum为不同语言的某些字段添加描述,例如以下示例:

public enum Status {

    ACT(new String[] { "Accepted", "مقبول" }),
    REJ(new String[] { "Rejected", "مرفوض" }),
    PND(new String[] { "Pending", "في الانتظار" }),
    ERR(new String[] { "Error", "خطأ" }),
    SNT(new String[] { "Sent", "أرسلت" });

    private String[] status;

    public String getDescription(String lang) {
        return lang.equals("en") ? status[0] : status[1];
    }

    Status(String[] status) {
        this.status = status;
    }
}

然后,您可以根据传递给getDescription(String lang)方法的语言代码来动态检索描述,例如:

String statusDescription = Status.valueOf("ACT").getDescription("en");

答案 25 :(得分:1)

由于尚未提到switch版,因此我对其进行了介绍(重用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);
      }
    }
  }

由于这不会给valueOf(String name)方法带来任何额外的价值,因此只有在我们想要具有不同的行为时才定义一个额外的方法才有意义。如果我们不想提出IllegalArgumentException,可以将实现更改为:

  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;
      }
    }
  }

通过提供默认值,我们保留了Enum.valueOf(String name)的{​​{3}},而不会抛出IllegalArgumentException,而不会返回null。因此,如果名称为NullPointerException,则抛出null;如果名称为default,则抛出defaultValuenullvalueOfOrDefault就是这样工作的。

此方法采用了Map-接口的设计,该接口提供了Java 8起的方法Map.getOrDefault(Object key, V defaultValue)

答案 26 :(得分:0)

获取枚举名称的最快方法是在应用程序启动时创建枚举文本和值的映射,并获取名称调用函数Blah.getEnumName():

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

    private String text;
    private HashMap<String, String> map;
    Blah(String text) {
    this.text = text;
    }

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

    static{
      createMapOfTextAndName();
    }

    public static void createMapOfTextAndName() {
        map = new HashMap<String, String>();
        for (Blah b : Blah.values()) {
             map.put(b.getText(),b.toString());
        }
    }
    public static String getEnumName(String text) {
        return map.get(text.toLowerCase());
    } 
}

答案 27 :(得分:0)

科特林溶液

创建一个扩展名,然后呼叫valueOf<MyEnum>("value")。如果类型无效,您将得到null并必须对其进行处理

inline fun <reified T : Enum<T>> valueOf(type: String): T? {
    return try {
        java.lang.Enum.valueOf(T::class.java, type)
    } catch (e: Exception) {
        null
    }
}

或者,您可以设置默认值,调用valueOf<MyEnum>("value", MyEnum.FALLBACK),并避免返回空值。您可以扩展特定的枚举,使其默认为自动

inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T {
    return try {
        java.lang.Enum.valueOf(T::class.java, type)
    } catch (e: Exception) {
        default
    }
}

或者,如果您想两者都做,则第二个:

inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default

答案 28 :(得分:0)

我喜欢使用这种过程将命令作为字符串解析为枚举。我通常将其中一个枚举称为“未知”,因此当找不到其他枚举时(即使在不区分大小写的情况下)而不是null(这意味着没有值),它会有所帮助。因此我使用这种方法。

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;
}

答案 29 :(得分:0)

Blah.valueOf("A") 是您要查找的语句,但请记住,这是区分大小写,因此 Blah.valueOf("a") 将不起作用并会生成异常。