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

Asked 2023-09-20 20:32:32 View 439,349

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?

Answers

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.

Answered   2023-09-20 20:32:32

  • For reference, the Blah.valueOf("A") method is case sensitive and doesn't tolerate extraneous whitespace, thus the alternate solution proposed below by @JoséMi. - anyone
  • @Michael Myers, Since this answer is the most voted up by far, should I understand that it's good practice to define an enum and its String value to be exactly the same? - anyone
  • @KevinMeredith: If you mean the toString() value, no, I wouldn't say that. name() will get you the actual defined name of the enum constant unless you override it. - anyone
  • What exactly do you mean by "are created at compile time and do not appear in source code." ? - anyone
  • @treesAreEverywhere More specifically, those methods are generated (or synthesized) by the compiler. The actual enum Blah {...} definition shouldn't try to declare its own values nor valuesOf. It's like how you can write "AnyTypeName.class" even though you never actually declared a "class" member variable; the compiler makes it all Just Work. (This answer may no longer be useful to you 3 months later, but just in case.) - anyone

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

Answered   2023-09-20 20:32:32

  • throw new IllegalArgumentException("No constant with text " + text + " found") would be better than return null. - anyone
  • @Sangdol usually it's a good thing to check what SUN - oops - Oracle is doing in the same situation. And as Enum.valueOf() is showing it IS best practice to throw a Exception in this case. Because it is an exceptional situation. "Performance optimization" is a bad excuse to write unreadable code ;-) - anyone
  • Here is a solution covering ignoring case sensitivity, and moves the solution from O(N) to O(1): stackoverflow.com/a/74408971/501113 - anyone

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

Answered   2023-09-20 20:32:32

  • This is even simpler in Java 8 as you can do :Stream.of(MyEnum.values()).collect(toMap(Enum::name, identity())) I also recommend overriding toString() (passed in through constructor) and using that instead of name, especially if the Enum is associated with serializable data as this lets you control the casing without giving Sonar a fit. - anyone
  • Static initialization is inherently synchronized, so there's absolutely no reason to use ConcurrentHashMap here, where the map is never modified after initialization. Hence why even e.g. the example in the JLS itself uses a regular HashMap. - anyone
  • In Kotlin this sort of looks like (without lowercase): ` private val mapStringToEnum by lazy { values().associateBy { it.name } } fun get(name: String): MyEnum? { return mapStringToEnum[name] } ` - anyone

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.

Answered   2023-09-20 20:32:32

  • That empty catch block really drives me nuts, sorry. - anyone
  • @LazloBonin: Exceptions are for exceptional conditions, not for control flow. Get yourself a copy of Effective Java. - anyone
  • Horrible! Always, always catch exceptions where you can handle them. The example above is a perfect example how to NOT do it. Why? So it returns NULL, and the caller then has to check against NULL or throw a NPE. If the caller knows how to handle the situation then doing an if vs. try-catch may look a bit more elegant, BUT if he can't handle he has to pass null again and the caller of the caller again has to check against NULL, etc. etc. - anyone
  • @whiskeysierra I understand being passionate about Java or software development is one thing but you gotta chill man. No benefit in geeking out/being extra like this. - anyone
  • What about returning Optional instead of nullable ? - anyone

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.

Answered   2023-09-20 20:32:32

  • Be wary of the default locale! - anyone

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

Answered   2023-09-20 20:32:32

  • Java 8 did some good things and while I like Streams (for concurrency mostly)... this is actually NOT a reason to use them. It buys the OP nothing and performs more poorly ... simply substituting a for/next loop through all items for a Stream version of the same (and not even in parallel). For a few entries.... who cares but to be clear, this is not some "it is way better because of Java 8" example. It's just a fluent-style green vs blue 'different' implementation of the same returning an Optional vs null (and fluent-style requires a non-null return for all joined methods). - anyone

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

Answered   2023-09-20 20:32:32

  • Good use of Generics but not sure IllegalArgumentException is really the right contract here. First, it is entirely possible (and expected?) that a lookup will fail... it is isn't in the collection (enum really) per se. Throwing a RuntimeException "propagate[s] outside the method". Since that is not in the method signature - a caller would not expect it. Better to use Map construct (return null on not found) or perhaps even better... Optional.empty(). - anyone

Using Blah.valueOf(string) is best, but you can use Enum.valueOf(Blah.class, string) as well.

Answered   2023-09-20 20:32:32

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:

  1. Direct conversion of types at HeaderParam annotation

Answered   2023-09-20 20:32:32

  • As on other answers already commented, what is the benefit or drawback of using streams for the conversion. This is the way I'd do it too, but I'm just curious why this approach is better than simple loops of calling of Enum.valueOf(class, value) - anyone

If you don't want to write your own utility, use Google's 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.

Answered   2023-09-20 20:32:32

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".

Answered   2023-09-20 20:32:32

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

Answered   2023-09-20 20:32:32

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

Answered   2023-09-20 20:32:32

  • Obfuscated code contest runner up? I mean this is technically correct. :-) ... but it is unessarily obtuse for a simple for/next loop over a Map - which arguably is no better an impl than earlier versions of Java could provide. private static final Map<String, MyEnumForJson> MAP = Stream.of(MyEnumForJson.values()).collect(Collectors.toMap(Object::toString, Function.identity())); - anyone
  • I think streams just look obtuse when you're used to for loops, but to each their own - anyone

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

Answered   2023-09-20 20:32:32

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

Answered   2023-09-20 20:32:32

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.

Answered   2023-09-20 20:32:32

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.

Answered   2023-09-20 20:32:32

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

}

Answered   2023-09-20 20:32:32

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

Answered   2023-09-20 20:32:32

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".

Answered   2023-09-20 20:32:32

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

Answered   2023-09-20 20:32:32

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

Answered   2023-09-20 20:32:32

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
}

Answered   2023-09-20 20:32:32

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.

Answered   2023-09-20 20:32:32

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

}

Answered   2023-09-20 20:32:32

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

Answered   2023-09-20 20:32:32

  • Instead of iterating every time when the getPositionForName() method is called we can create static Map holding name to Enum mapping. It will precompute the mapping and every method call will not iterate the enum values. As we are fetching it from map it is O(1) operation. - anyone

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").

Answered   2023-09-20 20:32:32

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

Answered   2023-09-20 20:32:32

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

Answered   2023-09-20 20:32:32

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

Answered   2023-09-20 20:32:32