How to retrieve a constant value by providing a string? - java

Considering this class
package com.bluegrass.core;
public class Constants {
public static final String AUTHOR="bossman";
public static final String COMPANY="Bluegrass";
//and many more constants below
}
I want to create a function that goes like this:
getConstantValue("AUTHOR") //this would return "bossman"
Any ideas how this can be done?

You can use reflection:
public static String getConstantValue(String name) {
try {
return (String) Constants.class.getDeclaredField(name).get(null);
} catch (Exception e) {
throw new IllegalArgumentException("Constant value not found: " + name, e);
}
}
UPDATE: Enum solution.
If you can change the Constants class to be an enum, it would be like this instead:
private static String getConstantValue(String name) {
return Constants.valueOf(name).getText();
}
But that requires something like this for Constants:
public enum Constants {
AUTHOR("bossman"),
COMPANY("Bluegrass");
private final String text;
private Constants(String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}

Probably the simplest solution (and also work with enums instead of String is typesafe) is to work with enum, provided you are able to change the public static final fields into an enum.
public enum Constants {
AUTHOR("bossman"),
COMPANY("Bluegrass");
private final String content;
Constants (String content) {
this.content= content;
}
public String getContent() {
return content;
}
public static Constants getConstant(String content) {
for (Constants constant : Constants.values()) {
if (constant.getContent().equals(content)) {
return constant;
}
}
return null; //default value
}
}
Usage:
Constants.valueOf("AUTHOR") == Constants.AUTHOR
Constants.getConstant("bossman") == Constants.AUTHOR
Constants.AUTHOR.getContent() == "bossman"
So instead of OP's getConstantValue("AUTHOR") it would be Constants.valueOf("AUTHOR").getContent()

There is a multitude of methods to solve this.
One way is to use a switch.
Example:
public String foo(String key) throws AnException {
switch (key) {
case case1:
return constString1;
case case2:
return constString2;
case case3:
return constString3;
...
default:
throws NotValidKeyException; //or something along these lines
}
}
The other method is to create a map<string,string> and fill it with the desired key,pairs.

Related

How to set Enum value from String value [duplicate]

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?
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.
Another solution if the text is not the same as 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;
}
}
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<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().toLowerCase(),instance);
}
ENUM_MAP = Collections.unmodifiableMap(map);
}
public static MyEnum get (String name) {
return ENUM_MAP.get(name.toLowerCase());
}
}
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
Here's a nifty utility I use:
/**
* 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;
}
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.
It is too bad I can't use T.class for Enum.valueOf as T is erased.
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.
On Android you should use Locale.US, as sulai points out.
In Java 8 or later, using 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 Optional<Blah> fromText(String text) {
return Arrays.stream(values())
.filter(bl -> bl.text.equalsIgnoreCase(text))
.findFirst();
}
}
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 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()
));
}
Using Blah.valueOf(string) is best, but you can use Enum.valueOf(Blah.class, string) as well.
My two cents here: using Java 8 Streams and 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 fromString(String s) throws IllegalArgumentException {
return Arrays.stream(MyEnum.values())
.filter(v -> v.value.equals(s))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("unknown value: " + s));
}
}
I renamed the function to fromString() since naming it using that convention, you'll obtain some benefits from Java language itself; for example:
Direct conversion of types at HeaderParam annotation
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.
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 the String method, it 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 example, if you provide "PERSON" in the fromEnumName it'll return you the Value of Enum, i.e., "Person".
Another way of doing this is by using the implicit static method name() of Enum. name will return the exact string used to create that enum which can be used to check against the 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
In Java 8 the static Map pattern is even easier and is my preferred 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<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);
}
}
Here is a 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 <Planet> possible = Enums.getIfPresent(Planet.class, val);
if (!possible.isPresent()) {
throw new IllegalArgumentException(val + "? There is no such planet!");
}
return possible.get();
}
}
Enum is very useful. I have been using Enum a lot to add a description for some fields in different languages, as the following example:
public enum Status {
ACT(new String[] { "Accepted", "مقبول" }),
REJ(new String[] { "Rejected", "مرفوض" }),
PND(new String[] { "Pending", "في الانتظار" }),
ERR(new String[] { "Error", "خطأ" }),
SNT(new String[] { "Sent", "أرسلت" });
private String[] status;
public String getDescription(String lang) {
return lang.equals("en") ? status[0] : status[1];
}
Status(String[] status) {
this.status = status;
}
}
And then you can retrieve the description dynamically based in the language code passed to the getDescription(String lang) method, for example:
String statusDescription = Status.valueOf("ACT").getDescription("en");
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 and parameter 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();
}
}
}
For those not aware, here's some more information on avoiding null with Optional.
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 Geoffrey Zheng's, but there isn't any need to roll your own when it's out there in the wild already.
An O(1) method inspired from Thrift-generated code which uses a hashmap.
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;
}
}
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 defines several useful methods, which is available to all enumeration types in Java:
You can use the name() method to get the name of any Enum constants. The string literal used to write enum constants is their name.
Similarly, the 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 the valueOf() method to convert any String to an 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, the valueOf() method returns an Enum constant, Gender.MALE, and calling name on that returns "MALE".
Use:
public enum MyEnum {
FIRST,
SECOND,
THIRD;
public static Optional<MyEnum> fromString(String value) {
try {
return Optional.of(MyEnum.valueOf(value));
}catch(Exception e) {
return Optional.empty();
}
}
}
Adding on to Michael Myers' 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 extends Enum<T>> 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
}
Enum valueOf()
An enum class automatically gets a static valueOf() method in the class when compiled. The valueOf() method can be used to obtain an instance of the enum class for a given String value.
For example:
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(Strings.TWO.name());
}
enum Strings {
ONE, TWO, THREE
}
}
As a switch-version has not been mentioned yet I introduce it (reusing OP's enum):
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);
}
}
}
Since this don't give any additional value to the valueOf(String name) method, it only makes sense to define an additional method if we want have a different behavior. If we don't want to raise an IllegalArgumentException we can change the implementation to:
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;
}
}
}
By providing a default value we keep the contract of Enum.valueOf(String name) without throwing an IllegalArgumentException in that manner that in no case null is returned. Therefore we throw a NullPointerException if the name is null and in case of default if defaultValue is null. That's how valueOfOrDefault works.
This approach adopts the design of the Map-Interface which provides a method Map.getOrDefault(Object key, V defaultValue) as of Java 8.
I was looking for an answer to find the "blah" name and not its value (not the text). Based on Manu's answer, I find this code useful:
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 valueOfCode(String blahCode) throws IllegalArgumentException {
Blah blah = Arrays.stream(Blah.values())
.filter(val -> val.name().equals(blahCode))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Unable to resolve blah: " + blahCode));
return blah;
}
}
public enum ToggleStatusUpdate {
OFF("off", 1),
ON("on", 2);
private final String name;
private final int position;
private ToggleStatusUpdate(String name, int position) {
this.name = name;
this.position = position;
}
public String getName() {
return name;
}
public int getPosition() {
return position;
}
public static int getPositionForName(String name) {
for(ToggleStatusUpdate toggleStatusUpdate : ToggleStatusUpdate.values()) {
if (toggleStatusUpdate.getName().equals(name)) {
return toggleStatusUpdate.getPosition();
}
}
return -1;
}
public static void main(String[] args) {
System.out.println(ToggleStatusUpdate.getPositionForName("off"));
}
}
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 <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;
}
}
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").
A combination of answers and comments for Java 8 using Streams.
It creates a static Map for lookup with the opportunity of a default value, to prevent null checks.
public enum Blah {
A, B, C, D, INVALID
private static final Map<String, Blah> ENUM_MAP = Stream.of(Blah.values())
.collect(Collectors.toMap(Enum::name, Function.identity()));
public static Blah of(final String name) {
return ENUM_MAP.getOrDefault(name, INVALID);
}
}
// e.g.
Blah.of("A");
A
Blah.of("X")
INVALID
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 <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;
}
Kotlin Solution
Create an extension and then call valueOf<MyEnum>("value"). If the type is invalid, you'll get null and have to handle it
inline fun <reified T : Enum<T>> valueOf(type: String): T? {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: Exception) {
null
}
}
Alternatively, you can set a default value, calling valueOf<MyEnum>("value", MyEnum.FALLBACK), and avoiding a null response. You can extend your specific enum to have the default be automatic
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: Exception) {
default
}
}
Or if you want both, make the second:
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default

java enum get description value [duplicate]

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?
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.
Another solution if the text is not the same as 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;
}
}
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<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().toLowerCase(),instance);
}
ENUM_MAP = Collections.unmodifiableMap(map);
}
public static MyEnum get (String name) {
return ENUM_MAP.get(name.toLowerCase());
}
}
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
Here's a nifty utility I use:
/**
* 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;
}
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.
It is too bad I can't use T.class for Enum.valueOf as T is erased.
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.
On Android you should use Locale.US, as sulai points out.
In Java 8 or later, using 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 Optional<Blah> fromText(String text) {
return Arrays.stream(values())
.filter(bl -> bl.text.equalsIgnoreCase(text))
.findFirst();
}
}
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 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()
));
}
Using Blah.valueOf(string) is best, but you can use Enum.valueOf(Blah.class, string) as well.
My two cents here: using Java 8 Streams and 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 fromString(String s) throws IllegalArgumentException {
return Arrays.stream(MyEnum.values())
.filter(v -> v.value.equals(s))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("unknown value: " + s));
}
}
I renamed the function to fromString() since naming it using that convention, you'll obtain some benefits from Java language itself; for example:
Direct conversion of types at HeaderParam annotation
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.
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 the String method, it 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 example, if you provide "PERSON" in the fromEnumName it'll return you the Value of Enum, i.e., "Person".
Another way of doing this is by using the implicit static method name() of Enum. name will return the exact string used to create that enum which can be used to check against the 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
In Java 8 the static Map pattern is even easier and is my preferred 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<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);
}
}
Here is a 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 <Planet> possible = Enums.getIfPresent(Planet.class, val);
if (!possible.isPresent()) {
throw new IllegalArgumentException(val + "? There is no such planet!");
}
return possible.get();
}
}
Enum is very useful. I have been using Enum a lot to add a description for some fields in different languages, as the following example:
public enum Status {
ACT(new String[] { "Accepted", "مقبول" }),
REJ(new String[] { "Rejected", "مرفوض" }),
PND(new String[] { "Pending", "في الانتظار" }),
ERR(new String[] { "Error", "خطأ" }),
SNT(new String[] { "Sent", "أرسلت" });
private String[] status;
public String getDescription(String lang) {
return lang.equals("en") ? status[0] : status[1];
}
Status(String[] status) {
this.status = status;
}
}
And then you can retrieve the description dynamically based in the language code passed to the getDescription(String lang) method, for example:
String statusDescription = Status.valueOf("ACT").getDescription("en");
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 and parameter 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();
}
}
}
For those not aware, here's some more information on avoiding null with Optional.
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 Geoffrey Zheng's, but there isn't any need to roll your own when it's out there in the wild already.
An O(1) method inspired from Thrift-generated code which uses a hashmap.
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;
}
}
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 defines several useful methods, which is available to all enumeration types in Java:
You can use the name() method to get the name of any Enum constants. The string literal used to write enum constants is their name.
Similarly, the 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 the valueOf() method to convert any String to an 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, the valueOf() method returns an Enum constant, Gender.MALE, and calling name on that returns "MALE".
Use:
public enum MyEnum {
FIRST,
SECOND,
THIRD;
public static Optional<MyEnum> fromString(String value) {
try {
return Optional.of(MyEnum.valueOf(value));
}catch(Exception e) {
return Optional.empty();
}
}
}
Adding on to Michael Myers' 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 extends Enum<T>> 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
}
Enum valueOf()
An enum class automatically gets a static valueOf() method in the class when compiled. The valueOf() method can be used to obtain an instance of the enum class for a given String value.
For example:
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(Strings.TWO.name());
}
enum Strings {
ONE, TWO, THREE
}
}
As a switch-version has not been mentioned yet I introduce it (reusing OP's enum):
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);
}
}
}
Since this don't give any additional value to the valueOf(String name) method, it only makes sense to define an additional method if we want have a different behavior. If we don't want to raise an IllegalArgumentException we can change the implementation to:
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;
}
}
}
By providing a default value we keep the contract of Enum.valueOf(String name) without throwing an IllegalArgumentException in that manner that in no case null is returned. Therefore we throw a NullPointerException if the name is null and in case of default if defaultValue is null. That's how valueOfOrDefault works.
This approach adopts the design of the Map-Interface which provides a method Map.getOrDefault(Object key, V defaultValue) as of Java 8.
I was looking for an answer to find the "blah" name and not its value (not the text). Based on Manu's answer, I find this code useful:
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 valueOfCode(String blahCode) throws IllegalArgumentException {
Blah blah = Arrays.stream(Blah.values())
.filter(val -> val.name().equals(blahCode))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Unable to resolve blah: " + blahCode));
return blah;
}
}
public enum ToggleStatusUpdate {
OFF("off", 1),
ON("on", 2);
private final String name;
private final int position;
private ToggleStatusUpdate(String name, int position) {
this.name = name;
this.position = position;
}
public String getName() {
return name;
}
public int getPosition() {
return position;
}
public static int getPositionForName(String name) {
for(ToggleStatusUpdate toggleStatusUpdate : ToggleStatusUpdate.values()) {
if (toggleStatusUpdate.getName().equals(name)) {
return toggleStatusUpdate.getPosition();
}
}
return -1;
}
public static void main(String[] args) {
System.out.println(ToggleStatusUpdate.getPositionForName("off"));
}
}
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 <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;
}
}
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").
A combination of answers and comments for Java 8 using Streams.
It creates a static Map for lookup with the opportunity of a default value, to prevent null checks.
public enum Blah {
A, B, C, D, INVALID
private static final Map<String, Blah> ENUM_MAP = Stream.of(Blah.values())
.collect(Collectors.toMap(Enum::name, Function.identity()));
public static Blah of(final String name) {
return ENUM_MAP.getOrDefault(name, INVALID);
}
}
// e.g.
Blah.of("A");
A
Blah.of("X")
INVALID
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 <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;
}
Kotlin Solution
Create an extension and then call valueOf<MyEnum>("value"). If the type is invalid, you'll get null and have to handle it
inline fun <reified T : Enum<T>> valueOf(type: String): T? {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: Exception) {
null
}
}
Alternatively, you can set a default value, calling valueOf<MyEnum>("value", MyEnum.FALLBACK), and avoiding a null response. You can extend your specific enum to have the default be automatic
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: Exception) {
default
}
}
Or if you want both, make the second:
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default

Initializing enum variables in a comparison function [duplicate]

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?
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.
Another solution if the text is not the same as 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;
}
}
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<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().toLowerCase(),instance);
}
ENUM_MAP = Collections.unmodifiableMap(map);
}
public static MyEnum get (String name) {
return ENUM_MAP.get(name.toLowerCase());
}
}
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
Here's a nifty utility I use:
/**
* 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;
}
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.
It is too bad I can't use T.class for Enum.valueOf as T is erased.
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.
On Android you should use Locale.US, as sulai points out.
In Java 8 or later, using 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 Optional<Blah> fromText(String text) {
return Arrays.stream(values())
.filter(bl -> bl.text.equalsIgnoreCase(text))
.findFirst();
}
}
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 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()
));
}
Using Blah.valueOf(string) is best, but you can use Enum.valueOf(Blah.class, string) as well.
My two cents here: using Java 8 Streams and 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 fromString(String s) throws IllegalArgumentException {
return Arrays.stream(MyEnum.values())
.filter(v -> v.value.equals(s))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("unknown value: " + s));
}
}
I renamed the function to fromString() since naming it using that convention, you'll obtain some benefits from Java language itself; for example:
Direct conversion of types at HeaderParam annotation
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.
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 the String method, it 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 example, if you provide "PERSON" in the fromEnumName it'll return you the Value of Enum, i.e., "Person".
Another way of doing this is by using the implicit static method name() of Enum. name will return the exact string used to create that enum which can be used to check against the 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
In Java 8 the static Map pattern is even easier and is my preferred 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<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);
}
}
Here is a 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 <Planet> possible = Enums.getIfPresent(Planet.class, val);
if (!possible.isPresent()) {
throw new IllegalArgumentException(val + "? There is no such planet!");
}
return possible.get();
}
}
Enum is very useful. I have been using Enum a lot to add a description for some fields in different languages, as the following example:
public enum Status {
ACT(new String[] { "Accepted", "مقبول" }),
REJ(new String[] { "Rejected", "مرفوض" }),
PND(new String[] { "Pending", "في الانتظار" }),
ERR(new String[] { "Error", "خطأ" }),
SNT(new String[] { "Sent", "أرسلت" });
private String[] status;
public String getDescription(String lang) {
return lang.equals("en") ? status[0] : status[1];
}
Status(String[] status) {
this.status = status;
}
}
And then you can retrieve the description dynamically based in the language code passed to the getDescription(String lang) method, for example:
String statusDescription = Status.valueOf("ACT").getDescription("en");
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 and parameter 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();
}
}
}
For those not aware, here's some more information on avoiding null with Optional.
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 Geoffrey Zheng's, but there isn't any need to roll your own when it's out there in the wild already.
An O(1) method inspired from Thrift-generated code which uses a hashmap.
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;
}
}
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 defines several useful methods, which is available to all enumeration types in Java:
You can use the name() method to get the name of any Enum constants. The string literal used to write enum constants is their name.
Similarly, the 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 the valueOf() method to convert any String to an 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, the valueOf() method returns an Enum constant, Gender.MALE, and calling name on that returns "MALE".
Use:
public enum MyEnum {
FIRST,
SECOND,
THIRD;
public static Optional<MyEnum> fromString(String value) {
try {
return Optional.of(MyEnum.valueOf(value));
}catch(Exception e) {
return Optional.empty();
}
}
}
Adding on to Michael Myers' 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 extends Enum<T>> 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
}
Enum valueOf()
An enum class automatically gets a static valueOf() method in the class when compiled. The valueOf() method can be used to obtain an instance of the enum class for a given String value.
For example:
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(Strings.TWO.name());
}
enum Strings {
ONE, TWO, THREE
}
}
As a switch-version has not been mentioned yet I introduce it (reusing OP's enum):
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);
}
}
}
Since this don't give any additional value to the valueOf(String name) method, it only makes sense to define an additional method if we want have a different behavior. If we don't want to raise an IllegalArgumentException we can change the implementation to:
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;
}
}
}
By providing a default value we keep the contract of Enum.valueOf(String name) without throwing an IllegalArgumentException in that manner that in no case null is returned. Therefore we throw a NullPointerException if the name is null and in case of default if defaultValue is null. That's how valueOfOrDefault works.
This approach adopts the design of the Map-Interface which provides a method Map.getOrDefault(Object key, V defaultValue) as of Java 8.
I was looking for an answer to find the "blah" name and not its value (not the text). Based on Manu's answer, I find this code useful:
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 valueOfCode(String blahCode) throws IllegalArgumentException {
Blah blah = Arrays.stream(Blah.values())
.filter(val -> val.name().equals(blahCode))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Unable to resolve blah: " + blahCode));
return blah;
}
}
public enum ToggleStatusUpdate {
OFF("off", 1),
ON("on", 2);
private final String name;
private final int position;
private ToggleStatusUpdate(String name, int position) {
this.name = name;
this.position = position;
}
public String getName() {
return name;
}
public int getPosition() {
return position;
}
public static int getPositionForName(String name) {
for(ToggleStatusUpdate toggleStatusUpdate : ToggleStatusUpdate.values()) {
if (toggleStatusUpdate.getName().equals(name)) {
return toggleStatusUpdate.getPosition();
}
}
return -1;
}
public static void main(String[] args) {
System.out.println(ToggleStatusUpdate.getPositionForName("off"));
}
}
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 <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;
}
}
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").
A combination of answers and comments for Java 8 using Streams.
It creates a static Map for lookup with the opportunity of a default value, to prevent null checks.
public enum Blah {
A, B, C, D, INVALID
private static final Map<String, Blah> ENUM_MAP = Stream.of(Blah.values())
.collect(Collectors.toMap(Enum::name, Function.identity()));
public static Blah of(final String name) {
return ENUM_MAP.getOrDefault(name, INVALID);
}
}
// e.g.
Blah.of("A");
A
Blah.of("X")
INVALID
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 <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;
}
Kotlin Solution
Create an extension and then call valueOf<MyEnum>("value"). If the type is invalid, you'll get null and have to handle it
inline fun <reified T : Enum<T>> valueOf(type: String): T? {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: Exception) {
null
}
}
Alternatively, you can set a default value, calling valueOf<MyEnum>("value", MyEnum.FALLBACK), and avoiding a null response. You can extend your specific enum to have the default be automatic
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: Exception) {
default
}
}
Or if you want both, make the second:
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default

How do i create a string enum types without overriding toString method to be used in Mule Studio?

I'm working with Mule Studio in this, and I actually was wondering the possibility to add the drop down list with a "custom" string name. The case applies for MIME Types (ContentTypes) names. (i.e: text/css, text/javascript, and so)
Made an structure like this:
public enum HttpContentType {
TEXT_PLAIN
{
public String toString() {
return "text/plain";
}
},
TEXT_CSS
{
public String toString() {
return "text/css";
}
},
TEXT_JS
{
public String toString() {
return "text/javascript";
}
},
TEXT_XML
{
public String toString() {
return "text/xml";
}
},
};
To then be used like this as a Configurable attribute:
/**
* Connection Content Types
*/
#Configurable
#Placement(order=1,group="Configuration",tab="HTTP Configuration")
private HttpContentType contentType;
But of course that when reading that from the Mule Studio it will be a Drop Down list with names such as: TEXT_CSS, TEXT_XML, TEXT_JAVASCRIPT ( http://puu.sh/3vLbd.png ) and so instead of text/css, text/xml, text/javascript.
How can i achieve this result?
A far better way to achieve this would be to provide a field in your enum, and provide an appropriate constructor:
public enum HttpContentType {
TEXT_PLAIN("text/plain"),
TEXT_CSS("text/css");
private String value;
HttpContentType(String value) {
this.value = value;
}
public String toString() {
return this.value;
}
public static HttpContentType getByValue(String value){
for (final HttpContentType element : EnumSet.allOf(HttpContentType.class)) {
if (element.toString().equals(value)) {
return element;
}
}
return null;
}
}
One option is to provide a different method to get the MIME string.
public interface IMimeTypeProvider {
public String toMimeType();
}
public enum HttpContentType implements IMimeTypeProvider {
TEXT_PLAIN
{
public String toMimeType() {
return "text/plain";
}
},
...
public String toMimeType() {
return "text/plain";
}
}
You might also consider adding a toDisplayString() method. The enumerator name is not necessarily a good display name, even in a single locale.
public enum HttpContentType {
TEXT_PLAIN("text/plain"), TEXT_CSS("text/css");
private String code;
HttpContentType(String code) {
this.code = code;
}
public String toString() {
return code;
}
public static HttpContentType getEnum(String code) {
if (code.equals("text/plain")) {
return TEXT_PLAIN;
} else if (code.equals("text/css")) {
return TEXT_CSS;
} else {
return null;
}
}
}

How to get an enum value from a string value in Java

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?
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.
Another solution if the text is not the same as 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;
}
}
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<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().toLowerCase(),instance);
}
ENUM_MAP = Collections.unmodifiableMap(map);
}
public static MyEnum get (String name) {
return ENUM_MAP.get(name.toLowerCase());
}
}
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
Here's a nifty utility I use:
/**
* 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;
}
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.
It is too bad I can't use T.class for Enum.valueOf as T is erased.
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.
On Android you should use Locale.US, as sulai points out.
In Java 8 or later, using 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 Optional<Blah> fromText(String text) {
return Arrays.stream(values())
.filter(bl -> bl.text.equalsIgnoreCase(text))
.findFirst();
}
}
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 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()
));
}
Using Blah.valueOf(string) is best, but you can use Enum.valueOf(Blah.class, string) as well.
My two cents here: using Java 8 Streams and 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 fromString(String s) throws IllegalArgumentException {
return Arrays.stream(MyEnum.values())
.filter(v -> v.value.equals(s))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("unknown value: " + s));
}
}
I renamed the function to fromString() since naming it using that convention, you'll obtain some benefits from Java language itself; for example:
Direct conversion of types at HeaderParam annotation
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.
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 the String method, it 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 example, if you provide "PERSON" in the fromEnumName it'll return you the Value of Enum, i.e., "Person".
Another way of doing this is by using the implicit static method name() of Enum. name will return the exact string used to create that enum which can be used to check against the 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
In Java 8 the static Map pattern is even easier and is my preferred 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<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);
}
}
Here is a 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 <Planet> possible = Enums.getIfPresent(Planet.class, val);
if (!possible.isPresent()) {
throw new IllegalArgumentException(val + "? There is no such planet!");
}
return possible.get();
}
}
Enum is very useful. I have been using Enum a lot to add a description for some fields in different languages, as the following example:
public enum Status {
ACT(new String[] { "Accepted", "مقبول" }),
REJ(new String[] { "Rejected", "مرفوض" }),
PND(new String[] { "Pending", "في الانتظار" }),
ERR(new String[] { "Error", "خطأ" }),
SNT(new String[] { "Sent", "أرسلت" });
private String[] status;
public String getDescription(String lang) {
return lang.equals("en") ? status[0] : status[1];
}
Status(String[] status) {
this.status = status;
}
}
And then you can retrieve the description dynamically based in the language code passed to the getDescription(String lang) method, for example:
String statusDescription = Status.valueOf("ACT").getDescription("en");
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 and parameter 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();
}
}
}
For those not aware, here's some more information on avoiding null with Optional.
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 Geoffrey Zheng's, but there isn't any need to roll your own when it's out there in the wild already.
An O(1) method inspired from Thrift-generated code which uses a hashmap.
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;
}
}
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 defines several useful methods, which is available to all enumeration types in Java:
You can use the name() method to get the name of any Enum constants. The string literal used to write enum constants is their name.
Similarly, the 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 the valueOf() method to convert any String to an 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, the valueOf() method returns an Enum constant, Gender.MALE, and calling name on that returns "MALE".
Use:
public enum MyEnum {
FIRST,
SECOND,
THIRD;
public static Optional<MyEnum> fromString(String value) {
try {
return Optional.of(MyEnum.valueOf(value));
}catch(Exception e) {
return Optional.empty();
}
}
}
Adding on to Michael Myers' 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 extends Enum<T>> 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
}
Enum valueOf()
An enum class automatically gets a static valueOf() method in the class when compiled. The valueOf() method can be used to obtain an instance of the enum class for a given String value.
For example:
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(Strings.TWO.name());
}
enum Strings {
ONE, TWO, THREE
}
}
As a switch-version has not been mentioned yet I introduce it (reusing OP's enum):
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);
}
}
}
Since this don't give any additional value to the valueOf(String name) method, it only makes sense to define an additional method if we want have a different behavior. If we don't want to raise an IllegalArgumentException we can change the implementation to:
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;
}
}
}
By providing a default value we keep the contract of Enum.valueOf(String name) without throwing an IllegalArgumentException in that manner that in no case null is returned. Therefore we throw a NullPointerException if the name is null and in case of default if defaultValue is null. That's how valueOfOrDefault works.
This approach adopts the design of the Map-Interface which provides a method Map.getOrDefault(Object key, V defaultValue) as of Java 8.
I was looking for an answer to find the "blah" name and not its value (not the text). Based on Manu's answer, I find this code useful:
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 valueOfCode(String blahCode) throws IllegalArgumentException {
Blah blah = Arrays.stream(Blah.values())
.filter(val -> val.name().equals(blahCode))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Unable to resolve blah: " + blahCode));
return blah;
}
}
public enum ToggleStatusUpdate {
OFF("off", 1),
ON("on", 2);
private final String name;
private final int position;
private ToggleStatusUpdate(String name, int position) {
this.name = name;
this.position = position;
}
public String getName() {
return name;
}
public int getPosition() {
return position;
}
public static int getPositionForName(String name) {
for(ToggleStatusUpdate toggleStatusUpdate : ToggleStatusUpdate.values()) {
if (toggleStatusUpdate.getName().equals(name)) {
return toggleStatusUpdate.getPosition();
}
}
return -1;
}
public static void main(String[] args) {
System.out.println(ToggleStatusUpdate.getPositionForName("off"));
}
}
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 <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;
}
}
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").
A combination of answers and comments for Java 8 using Streams.
It creates a static Map for lookup with the opportunity of a default value, to prevent null checks.
public enum Blah {
A, B, C, D, INVALID
private static final Map<String, Blah> ENUM_MAP = Stream.of(Blah.values())
.collect(Collectors.toMap(Enum::name, Function.identity()));
public static Blah of(final String name) {
return ENUM_MAP.getOrDefault(name, INVALID);
}
}
// e.g.
Blah.of("A");
A
Blah.of("X")
INVALID
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 <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;
}
Kotlin Solution
Create an extension and then call valueOf<MyEnum>("value"). If the type is invalid, you'll get null and have to handle it
inline fun <reified T : Enum<T>> valueOf(type: String): T? {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: Exception) {
null
}
}
Alternatively, you can set a default value, calling valueOf<MyEnum>("value", MyEnum.FALLBACK), and avoiding a null response. You can extend your specific enum to have the default be automatic
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: Exception) {
default
}
}
Or if you want both, make the second:
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default

Categories

Resources