How to get an enum value from a string value in Java?
假设我有一个枚举
1 2 3 | public enum Blah { A, B, C, D } |
我想找到一个字符串的枚举值,例如
我需要的方法是
是的,
注意,名称必须完全匹配,包括case:
静态方法
如果文本与枚举值不同,则另一个解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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; } } |
我使用的是一个漂亮的实用程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /** * 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; } |
然后在我的枚举类中,我通常使用这个来保存一些输入:
1 2 3 |
如果您的Enum不是全部大写,只需更改
太糟糕了,我不能用
你也应该小心处理你的案件。让我解释一下:做
编辑基于tc将
编辑2苏莱指出,在安卓系统上,你应该使用
使用Joshua Bloch的模式,有效的Java:
(为了简洁而简化)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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示例
枚举类型中静态块的执行顺序
如何从字符串值中查找JavaEnUM
这里有一个方法可以对任何枚举执行此操作,并且不区分大小写。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /** * 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() )); } |
使用
如果您不想编写自己的实用程序,请使用谷歌的guava库:
1 | Enums.getIfPresent(Blah.class,"A") |
与内置的Java函数不同,它让我们检查是否存在BLAH,并且不会抛出异常。
这里我的2分:使用Java8流+检查精确的字符串:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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)); } } |
**编辑**
将函数改名为EDCOX1×4,因为使用该约定命名它,您将从Java语言本身获得一些好处;例如:
在Java 8或更高版本中,使用流:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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); } } |
您可能需要这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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; } } |
再加一个:
1 2 3 4 5 6 7 8 9 10 |
这将按字符串化的枚举名称返回值,例如,如果在fromEnumName中提供"person",它将返回枚举的值,即"person"。
另一种方法是使用枚举的隐式静态方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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"); } } |
测试:
1 | //it will print B B |
灵感:Java中枚举的10个例子
使用guava库的解决方案。方法getPlanet()不区分大小写,因此GetPlanet("Mercury")将返回Planet.Mercury。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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(); } } |
为了增加前面的答案,并解决一些关于空值和NPE的讨论,我使用了guava选项来处理缺席/无效的案例。这对于URI/参数解析非常有用。
1 2 3 4 5 6 7 8 9 10 | 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(); } } } |
对于那些不知道的人,这里有一些关于使用可选选项避免空值的更多信息:https://code.google.com/p/guava-libraries/wiki/usingandvoidingnullExplained可选
在Java 8中,静态映射模式更容易,是我的预处理方法。如果要将枚举与Jackson一起使用,可以重写toString并使用它而不是名称,然后使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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); } } |
1 2 3 4 5 6 7 8 9 10 11 | 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)方法的灵感来源于节俭的代码,该代码使用哈希图。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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; } } |
Apache的commons lang库有一个静态函数org.apache.commons.lang3.enumutils.getenum,它将字符串映射到枚举类型。基本上和杰弗里斯的答案一样,但为什么当它已经在野外的时候,还要自己滚呢?
添加到最热门的答案,有一个有用的实用程序…
IllegalArgumentException NullPointerExeption
如果您的要求是这样的,您没有任何保证您的字符串一定会匹配枚举值,例如,如果字符串数据来自数据库并且可能包含枚举的旧版本,那么您需要经常处理这些…
所以这里有一个我编写的可重用方法,它允许我们定义一个默认的枚举,如果我们传递的字符串不匹配,它将被返回。
1 2 3 4 5 6 7 | 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; } } |
这样使用:
1 2 3 4 5 6 7 8 9 | 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 } |
EDCOX1 22定义了几种有用的方法,这些方法对于Java中的所有枚举类型都是可用的:
- 可以使用
name() 方法获取任何枚举常量的名称。用于写入枚举常量的字符串文字是它们的名称。 - 同样,可以使用
values() 方法从枚举类型中获取所有枚举常量的数组。 - 对于被问及的问题,如图所示,可以使用EDCOX1×5的方法将Java中的任何字符串转换为EnUM常量。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
在这段代码中,
怎么样?
1 2 3 4 5 6 7 8 9 10 11 12 13 |
以相反的方式捕获另一个实用程序。使用标识该枚举的值,而不是其名称。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.EnumSet; public class EnumUtil { /** * Returns the <wyn>Enum</wyn> of type <wyn>enumType</wyn> whose a * public method return value of this Enum is * equal to <wyn>valor</wyn>.<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 <wyn>Enum</wyn> of type <wyn>enumType</wyn> whose * public method <wyn>methodName</wyn> return is * equal to <wyn>value</wyn>.<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; } } |
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
由于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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); } } } |
因为这不会给
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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; } } } |
通过提供违约价值,我们保留了
该方法采用EDCOX1×17接口的设计,提供了Java 8的EDOCX1×18的方法。
获取枚举名称的最快方法是在应用程序启动时创建枚举文本和值的映射,并获取名称调用函数blah.getEnumName():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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()); } } |
我喜欢使用这种过程将命令作为字符串解析为枚举。我通常将其中一个枚举设置为"未知",因此在未找到其他枚举时返回(即使是在不区分大小写的基础上),而不是空枚举(这意味着没有值)会有所帮助。因此我使用这种方法。
1 2 3 4 5 6 7 8 9 10 11 12 | 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; } |