可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Say I have an enum which is just
public enum Blah { A, B, C, D }
and I would like to find the enum value of a string, for example "A" which would be Blah.A. How would it be possible to do this?
Is the Enum.valueOf() the method I need? If so, how would I use this?
回答1:
Yes, Blah.valueOf("A") will give you Blah.A.
Note that the name must be an exact match, including case: Blah.valueOf("a") and Blah.valueOf("A ") both throw an IllegalArgumentException.
The static methods valueOf() and values() are created at compile time and do not appear in source code. They do appear in Javadoc, though; for example, Dialog.ModalityType shows both methods.
回答2:
Another solution if the text is not the same to the enumeration value:
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; } }
回答3:
Here's a nifty utility I use:
/** * 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; }
Then in my enum class I usually have this to save some typing:
public static MyEnum fromString(String name) { return getEnumFromString(MyEnum.class, name); }
If your enums are not all caps, just change the Enum.valueOf line.
Too bad I can't use T.class for Enum.valueOf as T is erased.
回答4:
You should also be careful with your case. Let me explain: doing Blah.valueOf("A") works, but Blah.valueOf("a") will not work. Then again Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) would work.
edit
Changed toUpperCase to toUpperCase(Locale.ENGLISH) based on tc. comment and the java docs
edit2 On android you should use Locale.US, as sulai points out.
回答5:
Here's a method that can do it for any Enum, and is case insensitive.
/** * 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() )); }
回答6:
Use the pattern from Joshua Bloch, Effective Java:
(simplified for brevity)
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); } }
Also see:
Oracle Java Example using Enum and Map of instances
Execution order of of static blocks in an Enum type
How can I lookup a Java enum from its String value
回答7:
Using Blah.valueOf(string) is best but you can use Enum.valueOf(Blah.class, string) as well.
回答8:
If you don't want to write your own utility use Google's guava library:
Enums.getIfPresent(Blah.class, "A")
Unlike the built in java function it let's you check if A is present in Blah and doesn't throw an exception.
回答9:
You may need to this :
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; } }
One More Addition :
public static String fromEnumName(String parameterName) { if (parameterName != null) { for (DQJ objType : DQJ.values()) { if (parameterName.equalsIgnoreCase(objType.name())) { return objType.parameterName; } } } return null; }
This will return you the Value by a Stringified Enum Name For e.g. if you provide "PERSON" in the fromEnumName it'll return you the Value of Enum i.e. "Person"
回答10:
Another way of doing this by using implicit static method name() of Enum. name will return the exact string used to create that enum which can be used to check against provided 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 B B
inspiration: 10 Examples of Enum in Java
回答11:
Solution using Guava libraries. Method getPlanet () is case insensitive, so getPlanet ("MerCUrY") will return 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(); } }
回答12:
To add to the previous answers, and address some of the discussions around nulls and NPE I'm using Guava Optionals to handle absent/invalid cases. This works great for URI/parameter parsing.
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(); } } }
For those not aware, here's some more info on avoiding null with Optional: https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional
回答13:
My 2 cents here: using Java8 Streams + checking an exact 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 { return Arrays.stream(MyEnum.values()) .filter(v -> v.value.equals(s)) .findFirst(); .orElseThrow(() -> new IllegalArgumentException("unknown value: " + s)); } }
回答14:
public static MyEnum getFromValue(String value) { MyEnum resp = null; MyEnum nodes[] = values(); for(int i = 0; i
回答15:
O(1) method inspired from thrift generated code which utilize a hashmap.
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; } }
回答16:
In 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); } }
回答17:
java.lang.Enum defines several useful methods, which is available to all enumeration type in Java:
- You can use
name() method to get name of any Enum constants. String literal used to write enum constants is their name. - Similarly
values() method can be used to get an array of all Enum constants from an Enum type. - And for the asked question, you can use
valueOf() method to convert any String to Enum constant in Java, as shown below.
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
In this code snippet, valueOf() method returns an Enum constant Gender.MALE, calling name on that returns "MALE".
回答18:
In Java 8 the static Map pattern is even easier and is my preffered method. If you want to use the Enum with Jackson you can override toString and use that instead of name, then annotate with @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); } }
回答19:
Apache's commons-lang library has a static function org.apache.commons.lang3.EnumUtils.getEnum which will map a String to your Enum type. Same answer essentially as Geoffreys but why roll your own when it's out there in the wild already.
回答20:
Another utility capturing in reverse way. Using a value which identify that Enum, not from its name.
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; } }
Example:
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") returns Foo.THREE, because it will use getValue to match "drei", which is unique public, not final and not static method in Foo. In case Foo has more than on public, not final and not static method, for example, getTranslate which returns "drei", the other method can be used: EnumUtil.from(Foo.class, "drei", "getTranslate").
回答21:
Adding on to the top rated answer, with a helpful utility...
valueOf() throws two different Exceptions in cases where it doesn't like its input.
IllegalArgumentException NullPointerExeption
If your requirements are such that you don't have any guarantee that your String will definitely match an enum value, for example if the String data comes from a database and could contain old version of the enum, then you'll need to handle these often...
So here's a reusable method I wrote which allows us to define a default Enum to be returned if the String we pass doesn't match.
private static > T valueOf( String name , T defaultVal) { try { return Enum.valueOf(defaultVal.getDeclaringClass() , name); } catch (IllegalArgumentException | NullPointerException e) { return defaultVal; } }
Use it like this:
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 }
回答22:
I like to use this sort of process to parse commands as strings into enumerations. I normally have one of the enumerations as "unknown" so it helps to have that returned when the others are not found (even on a case insensitive basis) rather than null (that meaning there is no value). Hence I use this approach.
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; }
回答23:
What about?
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(); } } }