如何从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  Enum type * @param c enum type. All enums must be all caps. * @param string case insensitive * @return corresponding enum, or null */ public static > T getEnumFromString(Class 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被删除,我不能将T.class用于Enum.valueOf

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

编辑
基于tc将 toUpperCase(Locale.ENGLISH)更改为toUpperCase(Locale.ENGLISH) 。 评论和java文档

edit2在Android上你应该使用Locale.US ,正如sulai指出的那样 。

使用来自Joshua Bloch, Effective Java的模式:

(为简洁起见,简化)

 enum MyEnum { ENUM_1("A"), ENUM_2("B"); private String name; private static final Map 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 map = new ConcurrentHashMap(); 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); } } 

另见:

使用Enum和实例映射的Oracle Java示例

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

如何从String值中查找Java枚举

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

 /** * Finds the value of the given enumeration by name, case-insensitive. * Throws an IllegalArgumentException if no match is found. **/ public static > T valueOfIgnoreCase( Class 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)

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

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

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

您可能需要这样:

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

这将通过字符串化的枚举名称返回值。例如,如果您在fromEnumName中提供“PERSON”,它将返回Enum的值,即“Person”

在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 Blah fromText(String text) { return Arrays.stream(values()) .filter(bl -> bl.text.equalsIgnoreCase(text)) .findFirst() .orElse(null); } } 

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

 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注释中直接转换类型

另一种方法是使用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 BB 

灵感: 10个Java中Enum的例子

使用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  possible = Enums.getIfPresent(Planet.class, val); if (!possible.isPresent()) { throw new IllegalArgumentException(val + "? There is no such planet!"); } return possible.get(); } } 

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

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

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

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

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

 public enum USER { STUDENT("jon",0),TEACHER("tom",1); private static final Map 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; } } 

在Java 8中,静态Map模式更容易,是我的优先方法。 如果你想使用Enum with Jackson,你可以覆盖toString并使用它代替名称,然后使用@JsonValue进行注释

 public enum MyEnum { BAR, BAZ; private static final Map 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 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); } } 

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

  • 您可以使用name()方法获取任何Enum常量的名称。 用于编写枚举常量的字符串文字是它们的名称。
  • 类似地, values()方法可用于从Enum类型获取所有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()方法返回一个Enum常量Gender.MALE,调用name返回"MALE"

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

添加到最受好评的答案,有用的实用程序……

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

  • IllegalArgumentException
  • NullPointerExeption

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

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

 private static > 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 } 

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

 import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.EnumSet; public class EnumUtil { /** * Returns the Enum of type enumType whose a * public method return value of this Enum is * equal to valor.
* 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 from(Class enumType, Object value) { String methodName = getMethodIdentifier(enumType); return from(enumType, value, methodName); } /** * Returns the Enum of type enumType whose * public method methodName return is * equal to value.
* * @param enumType * @param value * @param methodName * @return */ public static
> E from(Class enumType, Object value, String methodName) { EnumSet 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 ,因为它将使用getValue匹配“drei”,这是唯一的公共,而不是Foo中的final和非静态方法。 如果Foo不仅仅是public,而不是final和非static方法,例如getTranslate返回“drei”,则可以使用另一种方法: EnumUtil.from(Foo.class, "drei", "getTranslate")

关于什么?

 public enum MyEnum { FIRST, SECOND, THIRD; public static Optional fromString(String value){ try{ return Optional.of(MyEnum.valueOf(value)); }catch(Exception e){ return Optional.empty(); } } } 

由于尚未提及switch -version,我将其介绍(重用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)的约定 ,而不会以这种方式抛出IllegalArgumentException ,在任何情况下都不返回null 。 因此,如果名称为null ,则抛出NullPointerException ;如果defaultValuenullnull default null 。 这就是valueOfOrDefault工作原理。

这种方法采用Map -Interface的设计,从Java 8开始提供方法Map.getOrDefault(Object key, V defaultValue)

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

 static > Enum getEnumValue(String what, Class enumClass) { Enum unknown=null; for (Enum enumVal: enumClass.getEnumConstants()) { if (what.compareToIgnoreCase(enumVal.name()) == 0) { return enumVal; } if (enumVal.name().compareToIgnoreCase("unknown") == 0) { unknown=enumVal; } } return unknown; }