通过string值查找枚举

说我有一个枚举,这只是

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

我想find一个string的枚举值,例如"A" ,这将是Blah.A 怎么可能做到这一点?

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

是的, Blah.valueOf("A")会给你Blah.A

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

静态方法valueOf()values()是在编译时创build的,不会出现在源代码中。 不过他们确实出现在Javadoc中; 例如, Dialog.ModalityType显示两个方法。

另一个解决scheme是如果文本与枚举值不一致:

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

然后在我的枚举类,我通常有这个保存一些input:

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

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

太糟糕了,我不能使用T.class Enum.valueOf作为T被删除。

你也应该小心你的情况。 让我解释一下:做Blah.valueOf("A")工作,但Blah.valueOf("a")将无法正常工作。 然后再Blah.valueOf("a".toUpperCase(Locale.ENGLISH))将工作。

编辑
基于tc更改为toUpperCase(Locale.ENGLISH) 。 评论和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)

使用来自Joshua Bloch, Effective 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(),instance); } ENUM_MAP = Collections.unmodifiableMap(map); } public static MyEnum get (String name) { return ENUM_MAP.get(name); } } 

另请参阅:

Oracle Java示例使用Enum和Map实例

静态块的枚举types的执行顺序

我怎样才能从它的string值查找Java枚举

如果你不想编写自己的工具,可以使用Google的番石榴图书馆:

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

这将返回值的一个string化的枚举名称例如,如果你在fromEnumName中提供“PERSON”它会返回你的枚举值,即“人”

另一种方法是使用Enum的隐式静态方法name() 。 name将返回用于创build该枚举的确切string,可用于检查提供的string:

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

testing:

System.out.println(Blah.getEnum("B").name());

 //it will print BB 

灵感: Java中的Enum的10个例子

解决scheme使用番石榴库。 方法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(); } } 

为了增加以前的答案,并解决一些围绕空值和NPE的讨论,我使用Guava Optionals处理缺席/无效的案例。 这对URI /参数parsing非常有用。

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

对于那些不知道的,这里有一些关于避免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; } 

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

  • 您可以使用name()方法来获取任何枚举常量的名称。 用于写入枚举常量的string文字是它们的名字。
  • 类似的, values()方法可以用来从Enumtypes中获得所有Enum常量的数组。
  • 对于被问的问题,可以使用valueOf()方法将任何string转换为Java中的枚举常量,如下所示。
 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()方法返回一个枚举常量Gender.MALE,调用名字返回"MALE"

O(1)方法灵感来自使用散列映射的节俭生成代码。

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

在Java 8中,静态的Map模式更容易,是我的优先方法。 如果你想用Jackson的Enum,你可以重写toString并使用它来代替name,然后用@JsonValue

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

我的2分钱在这里:使用Java8 Streams +检查确切的string:

 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 asEnumValue(String s) throws IllegalArgumentException { Optional<MyEnum> enumValue = Arrays .stream(MyEnum.values()) .filter((v) -> v.value.equals(s)) .findFirst(); return enumValue.orElseThrow(() -> new IllegalArgumentException("unknown value:" + s)); } } 

Apache的commons-lang库有一个静态函数org.apache.commons.lang3.EnumUtils.getEnum ,它将一个string映射到你的枚举types。 和Geoffreys基本上是一样的,但是为什么在野外已经有了自己呢?

另一个实用程序捕获的方式。 使用一个标识Enum的值,而不是从它的名字。

 import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.EnumSet; public class EnumUtil { /** * Returns the <code>Enum</code> of type <code>enumType</code> whose a * public method return value of this Enum is * equal to <code>valor</code>.<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 <code>Enum</code> of type <code>enumType</code> whose * public method <code>methodName</code> return is * equal to <code>value</code>.<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; } } 

例:

 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中唯一的public,不是最终的,也不是static方法。 如果Foo比公有的要多,而不是最终的而不是静态的方法,例如getTranslate返回“drei”,另一个方法可以使用: EnumUtil.from(Foo.class, "drei", "getTranslate")

添加到评分最高的答案,与一个有用的工具…

在不喜欢input的情况下, valueOf()会引发两个不同的exception。

  • IllegalArgumentException
  • NullPointerExeption

如果你的需求是这样的,你没有任何保证你的string肯定会匹配一个枚举值,例如,如果string数据来自数据库,可以包含旧版本的枚举,那么你需要处理这些经常…

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

 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 } 

在Java 8中:

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

我喜欢使用这种types的过程将命令parsing为枚举types的string。 我通常有一个枚举为“未知”,所以它有助于让其他人没有find(即使在不区分大小写的情况下)而不是null(这意味着没有任何价值)。 因此我使用这种方法。

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