假设我有一个枚举

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

我想找到一个字符串的枚举值,例如“a”,它将是Blah.a。如何做到这一点?

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


当前回答

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

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

然后在我的enum类中,我通常使用这个来保存一些类型:

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

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

太糟糕了,因为t被删除,我不能对Enum.valueOf使用t.class。

其他回答

使用Joshua Bloch《有效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().toLowerCase(),instance);
        }
        ENUM_MAP = Collections.unmodifiableMap(map);
    }

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

另请参见:

使用枚举和实例映射的Oracle Java示例

枚举类型中静态块的执行顺序

如何从Java枚举的String值查找它

为了补充前面的答案,并解决围绕空值和NPE的一些讨论,我使用Guava选项来处理缺席/无效的情况。这对于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避免null的更多信息。

Kotlin溶液

创建一个扩展,然后调用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.FALLACK),并避免空响应。您可以扩展特定枚举以使默认值为自动

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

在Michael Myers的回答中添加了一个有用的工具。。。

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

非法数据异常NullPointerEx选项

如果您的要求是这样的,那么您不能保证您的String一定会匹配枚举值,例如,如果String数据来自数据库并且可能包含旧版本的枚举,那么您需要经常处理这些。。。

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

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
}

这里有一个使用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();
   }
}