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

说我有一个枚举

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

我想找到一个字符串的枚举值,例如"A"就是Blah.A怎么可能做到这一点?

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

答案

是的, Blah.valueOf("A")将给您Blah.A

请注意,名称必须完全匹配,包括大小写: Blah.valueOf("a")Blah.valueOf("A ")都抛出IllegalArgumentException

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

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

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

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

/**
 * 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被删除了, Enum.valueOf我不能对Enum.valueOf使用T.class

使用有效 Java 的 Joshua Bloch 提供的模式:

(为简化起见)

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 示例

Enum 类型的静态块的执行顺序

如何从其 String 值查找 Java 枚举

您还应该谨慎对待自己的情况。让我解释一下:做Blah.valueOf("A")可以,但是Blah.valueOf("a")不能。然后再次使用Blah.valueOf("a".toUpperCase(Locale.ENGLISH))

编辑
改变toUpperCasetoUpperCase(Locale.ENGLISH)基于TC。注释Java 文档

EDIT2在 Android 上,你应该使用Locale.US ,作为sulai 指出

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

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

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

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

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

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

与内置的 Java 函数不同,它让您检查 Bl 中是否存在 A 且不引发异常。

我在这里的 2 美分:使用 Java8 流 + 检查确切的字符串:

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

** 编辑 **

由于使用该约定命名该函数,因此将该函数重命名为fromString() ,您将从 Java 语言本身中获得一些好处。例如:

  1. 直接在 HeaderParam 批注中转换类型