如何从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语言本身获得一些好处; 例如:
- 在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 typeenumType
whose a * public method return value of this Enum is * equal tovalor
.
* 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 typeenumType
whose * public methodmethodName
return is * equal tovalue
.
* * @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
;如果defaultValue
为null
则null
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; }