2128

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?

Steve Chambers
  • 31,993
  • 15
  • 129
  • 173
Malachi
  • 30,486
  • 16
  • 60
  • 96

29 Answers29

2411

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.

Michael Myers
  • 178,094
  • 41
  • 278
  • 290
  • 106
    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. – Brett Dec 17 '13 at 17:37
  • 3
    @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? – Kevin Meredith Feb 12 '14 at 21:24
  • 4
    @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. – Michael Myers Feb 14 '14 at 04:10
  • 4
    What exactly do you mean by "are created at compile time and do not appear in source code." ? – treesAreEverywhere Mar 07 '14 at 00:43
  • 8
    @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.) – Ti Strga May 30 '14 at 19:31
  • 1
    Great answer--in addition I've found adding a few little helper methods to enums helps a lot... For instance, if you create a static map of lower-case entries in the constructor then you can add a method that looks the enum up in a case-insensitive way, or converts underbars to spaces so user input like "Second Entry" could map to an enum SECOND_ENTRY. – Bill K Nov 19 '15 at 17:39
  • Why does @Brett's comment have so many votes? Of course it's case sensitive and doesn't tolerate extraneous whitespace, anything else would be insane. – nemetroid Jun 29 '17 at 08:54
  • @nemetroid Not that insane, given that whitespace is not allowed in names and that all enum names are uppecase by convention. So a tolerant lookup method is possible as the result stays unique. However, users may require something even more tolerant and therefore it's best to provide a canonical strict version (and there are other problems like uppercasing being locale-sensitive and whatever). – maaartinus Aug 21 '18 at 22:48
  • 1
    Upvote, but this post would be even better with a mention of Enum::name – Bex Aug 22 '18 at 14:27
  • This doesn't work on my case, I am still getting IllegalArgumentException. – Artanis Zeratul Mar 09 '21 at 00:27
  • @ArtanisZeratul: Sounds like it's not an exact case-correct match then. – Michael Myers Mar 09 '21 at 14:28
938

Another solution if the text is not the same to the enumeration value:

public enum Blah {
    A("text1"),
    B("text2"),
    C("text3"),
    D("text4");

    private String text;

    Blah(String text) {
        this.text = text;
    }

    public String getText() {
        return this.text;
    }

    public static Blah fromString(String text) {
        for (Blah b : Blah.values()) {
            if (b.text.equalsIgnoreCase(text)) {
                return b;
            }
        }
        return null;
    }
}
deHaar
  • 11,298
  • 10
  • 32
  • 38
JoséMi
  • 10,522
  • 2
  • 18
  • 22
  • 431
    `throw new IllegalArgumentException("No constant with text " + text + " found")` would be better than `return null`. – whiskeysierra Jul 31 '10 at 10:28
  • 8
    @whiskeysierra Jon Skeet wouldn't agree with that. http://stackoverflow.com/questions/1167982/check-if-enum-exists-in-java – Sanghyun Lee Sep 05 '11 at 04:06
  • 14
    @Sangdol Could *you* enlight us why returning null is better? – whiskeysierra Sep 29 '11 at 15:04
  • 2
    That comment is about the proposed answer of actually catching an exception to determine whether the string represents a valid enum value. You probably need a second method (e.g. isValid) for such a use case. – whiskeysierra Sep 29 '11 at 21:44
  • 63
    @Sangdol usually it's a good thing to check what SUN - oops - Oracle is doing in the same situation. And as [Enum.valueOf()](http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Enum.html#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 ;-) – raudi Feb 02 '12 at 07:43
  • 5
    Well, you could also make use of @Nullable annotation to make it "readable" ;-) – JoséMi Feb 03 '12 at 08:20
  • Ok, to convert a string into an enum constant, It is probably good to throw an exception in case of null or no match, same like valueOf does. However, think about how you would implement a method to test if a string is used by the enum constants ... example to get around all that at http://stackoverflow.com/a/12659023/744133 – YoYo Sep 30 '12 at 18:22
  • 3
    Concerning error handling it always depends on where the information comes from. If your values come from an external source (user input...) over which you have no control, catch the error and show some meaningful message if possible. In case the value passed to valueOf comes from your own internal code you should catch the errors and fail hard (log and crash) you probably have a bug and it can be fixed. – Christophe Roussy Nov 08 '12 at 10:29
  • I have a really dumb question... in your fromString method right after where you do the *equalsIgnoreCase* you have b.text. Text is a private member of the enum class how can you access it? – Jan Tacci Mar 24 '13 at 04:33
  • @Jan: Because the code itself is inside the enum class and, of course, it has visibility over all attributes and methods of that class. – JoséMi Mar 27 '13 at 06:16
  • 1
    @raudi I prefer null in this case, because when I go to get the value, I find it more pragmatic to check `if(returnval == null)` than catch the exception. It works better idealistically too: does it make more sense to return an empty result if it doesn't match? or throw an error? I think it makes more sense to return an empty result. – Tyzoid May 24 '13 at 14:05
  • 2
    @Tyzoid: I didn't say it's wrong I didn't even say it's bad practice, I just said that throwing an exception looks more appropriate. Think about what the caller has to do: if null is returned, then the return value has to be checked after each and every call unless you want to catch NPE, which you shouldn't ;-). Now look at what happens if an exception is thrown: The caller can decide on what level he wants to catch it: globally catch Exception, global catch the specific Exception or catch the specific Exception on single calls or any combination thereof. Surely a lot nicer to use... – raudi May 27 '13 at 17:05
  • 4
    @Tyzoid @raudi To be fair, especially if you are writing code to last and for others to use, the appropriate thing to do is something like what the `Queue` interface does with `remove` vs. `poll` -- have two versions of the method, one that returns `null` on (a very predictable and common) failure, and one that throws an exception, then let whoever is using it decide what to use based on what the larger application warrants. – trutheality May 29 '13 at 21:45
  • 2
    I guess `if (text == null) return null;` is better than `if (text != null) { ....} return null`. The first way is easier to understand. – Snicksie Aug 01 '13 at 07:16
  • 1
    "null sucks" -Doug Lea https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained – Kevin Meredith Dec 05 '13 at 21:21
  • `text.equalsIgnoreCase(b.text)` may throw null pointer exception if null is passed to `fromString()` whereas `b.text.equalsIgnoreCase(text)` will not (given the listed enum instances). – Gus Jun 28 '14 at 01:12
  • @Gus, please, read two lines before the one you says there is an error: `if (text != null) {`... – JoséMi Jul 02 '14 at 05:50
  • 1
    Sorry, wrote to fast... It's not an error. The null check can be avoided. This is just like `"foo".equals(bar)` instead of `bar.equals("foo")` – Gus Jul 05 '14 at 13:26
  • @JoséMi Might also be a good idea to override the default toString() and make it return 'text' – FearlessHyena Oct 03 '14 at 20:03
  • The addition of the `text` field and `getText()` methods is not necessary as the code could just as easily have used the automatically generated `name()` method. It is also possible to write a `public static > com.mylibs.Enums.fromString(E enumType, String s)` that would work for *any* Enum type. – Paul May 11 '16 at 16:46
  • 1
    An alternative in many cases is to have an explicit UNKNOWN value for the enum - that way you can avoid NPEs and still be able to check for unknown values. – chrisdowney Jul 12 '17 at 21:57
  • 4
    To be fair to Jon Skeet, the question he was answering was how to do this without throwing and catching an exception. The fact that he answered the question as asked doesn't mean he believes it's a good idea. @SanghyunLee – Dawood ibn Kareem Sep 14 '17 at 20:03
  • For what is worth, Kotlin… `The valueOf() method throws an IllegalArgumentException if the specified name does not match any of the enum constants defined in the class.` – Martin Marconcini Apr 10 '18 at 20:03
126

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.

Too bad I can't use T.class for Enum.valueOf as T is erased.

Geoffrey Zheng
  • 6,354
  • 2
  • 35
  • 47
  • 186
    That empty catch block really drives me nuts, sorry. – whiskeysierra Jul 31 '10 at 10:14
  • 33
    @LazloBonin: Exceptions are for exceptional conditions, not for control flow. Get yourself a copy of [Effective Java](http://java.sun.com/docs/books/effective/). – Martin Schröder Nov 15 '11 at 17:09
  • 10
    If the Java API you want to use throws an exception and you don't want your code to throw one, you can either swallow the exception like this, or re-write the logic from scratch so no exception is thrown in the first place. Swallowing the exception is often the lesser evil. – Nate C-K Nov 30 '11 at 19:26
  • 47
    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. – raudi Feb 02 '12 at 07:52
  • 10
    To be fair to the solution above, there are really uses cases requiring you to return null instead of throwing IllegalArgumentException and break the flow of your program, for instance, mapping enums between a web service schema and a database schema wherein they are not always one-to-one. However, I agree that the catch block should never be left empty. Put some code like log.warn or something for tracking purpose. – Adrian M Feb 06 '12 at 08:19
  • 1
    Absolutely! Logging the exception is a sure thing. But I agree with swallowing exceptions. – Manimaran Selvan May 17 '12 at 18:49
  • Now I would just use Guava's [Enums](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Enums.html). Note the different treatment of invalid input: `getIfPresent` returns `Optional.absent()`, which is what I'd prefer to use; whereas `valueOfFunction().apply()` returns `null`. – Geoffrey Zheng Aug 20 '12 at 20:28
  • 1
    The problems starts when you would want to write a static method that tests if a string matches an enum instance. The only way to test against the different enum values is to actually call the valueOf function. If it throws, result is false. – YoYo Sep 30 '12 at 05:18
  • 4
    Am I missing Something? What is the added value of the above methods compared to simply using: `MyEnum.valueOf(name)` ? – urig Feb 12 '13 at 08:37
  • 2
    @urig they're case insensitive, unlike `valueOf` – Brad Mace May 15 '14 at 19:49
  • 2
    If you're going to write a separate routine for case-insensitive comparison, then why not *really* do a case-insensitive check using `String.equalsIgnoreCase` instead of this hardcoded `toUpperCase`? – Stijn de Witt Jul 26 '15 at 13:29
  • Equivalent to [apache-common's EnumUtils](https://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/EnumUtils.html) getEnum method – pjklauser Oct 22 '15 at 06:47
  • @pjklauser No, EnumUtils' getEnum method does *not* do case insensitive lookup. – nemetroid Jun 29 '17 at 08:51
  • I like this utility. We've added a "default" parameter in case the enumeration cannot be determined: final @Nullable T def – Rob Stoecklein Jan 09 '18 at 18:59
  • 1
    A side-discussion now but... a better practice is to return an Optional if that is what is what was intended (e.g., could reasonably be "unknown/undefined"). Then NPE is gone and yet the lookup failure doesn't return an Exception as a means of control flow. – Darrell Teague Jan 14 '19 at 15:44
124

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

Darrell Teague
  • 3,531
  • 1
  • 23
  • 36
  • 5
    if Joshua Bloch said it then this is the only way to go :-). Its a shame that i always have to scroll down here. – dermoritz Jan 10 '17 at 09:51
  • 14
    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. – Novaterata Apr 27 '17 at 17:01
  • 1
    Java 8 certainly can/will change a lot of (better) answers on this forum. Not sure about ever having the tail (Sonar) wag the dog (application code) though. – Darrell Teague Apr 28 '17 at 20:31
  • 4
    If you're going to put it in an `unmodifiableMap` anyway, then there's no benefit to starting with a `ConcurrentHashMap`. Just use a `HashMap`. (If you have Guava's `ImmutableMap` then I'd recommend that instead!) – Daniel Pryden Mar 08 '18 at 16:13
  • Google's ImmutableMap is certainly a better (true deeply immutable) implementation but for the purpose of demonstrating an only-core-Java solution ... and focusing on the String map lookup case, only core-Java classes were used. In general, have found that ConcurrentHashMap is almost always preferred over HashMap given the overall performance profile (add, remove, modify) and simplicity versus wrapping/locking HashMap when concurrent modification has to be considered. – Darrell Teague Mar 09 '18 at 16:47
  • 11
    [Static initialization is inherently synchronized](https://docs.oracle.com/javase/specs/jls/se10/html/jls-12.html#jls-12.4.2), 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`. – Radiodef Aug 05 '18 at 17:24
  • The comment in code explicitly states "any map impl will do". For junior devs have found using ConcurrentHashMap as a common practice is preferrable in trade off with common sources of bugs in not synchronizing Map modifications generally. – Darrell Teague Aug 24 '18 at 16:48
  • 1
    @DarrellTeague - If we are in multithreaded environment, then it is mandatory to think about the consequences of our choices. Defensive use of synchronized collections without thought runs counter to the reasons why we have concurrency in the first place. I cannot see why a collection that in principle should be an Immutable Collection can benefit from being implemented as a Concurrent Collection. – YoYo Aug 29 '18 at 15:28
  • @YoYo - again as stated, any map impl will do and there is indeed no consequence, positive nor negative for the given impl. Please read prior comment about junior devs such that, all things considered, given that ConcurrentHashMap has no read performance penalty, has applicability as a general purpose Map impl, _generally_ over HashMap wherein developers must think very carefully about synchronization during update. Thus herein where ConcurrentHashMap _may_ be used with no consequence and _may_ be needed in other cases where synchronization is needed - this seems perfectly reasonable. – Darrell Teague Aug 31 '18 at 01:28
  • 1
    If that is your firm belief, then I should also advise on using `synchronized (map) { ENUM_MAP = Collections.unmodifiableMap(map); }` to avoid indeterministic behavior in a possible iterator being used inside the method for building the unmodifiable version - as a standard so that the junior dev does not have to think to much about those same consequences. See [Synchronized Wrappers](https://docs.oracle.com/javase/tutorial/collections/implementations/wrapper.html). – YoYo Aug 31 '18 at 02:15
  • Thanks @YoYo and that is a good impl snippet in context for others to understand implications of gaining access to iterators whilst maps are being constructed/updated - a subtle and difficult to debug case. – Darrell Teague Aug 31 '18 at 17:06
  • 1
    sorry but `ConcurrentHashMap` is completely useless there – Enerccio May 23 '19 at 08:21
  • I would use Streams and return a "NullObject" enum in case the value doesn't exist. Returning null is almost always worse than throwing an exception. – hfontanez Sep 11 '19 at 20:24
  • Agree that general contracts from Java for many methods returning null is not preferred over returning Optional - especially in light of Fluent style development. However, that is a newer construct. Still, if asking "does this value exist" - not sure it would make sense to return an Optional versus null that is clearly an indicator there is no such value such as in a Map.get() call wherein the key is not present. – Darrell Teague Apr 02 '20 at 20:33
  • To wrap up this whole "why use ConcurrentHashMap when you don't need it" discussion... there is no bug here. Further, there is no performance impact whatsoever. The result is exactly the same as with any other (non-null value) Map impl. The argument "but you don't need it" is understood but if one can get a car with same fuel efficiency and power etc at the same price as an inferior model - why wouldn't the superior car be purchased even if none of the (better) features are used? – Darrell Teague Apr 02 '20 at 20:38
  • Added case-insensitivity to lookup operation. Note that value returned from "getName()" still returns whatever the original value that was entered. Should put to bed the case-insensitive lookup discussion as a trivial modification to the implementation. – Darrell Teague Dec 30 '20 at 22:29
76

You should also be careful with your case. Let me explain: doing Blah.valueOf("A") works, but Blah.valueOf("a") will not work. Then again Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) would work.

edit
Changed toUpperCase to toUpperCase(Locale.ENGLISH) based on tc. comment and the java docs

edit2 On android you should use Locale.US, as sulai points out.

Community
  • 1
  • 1
João Portela
  • 5,592
  • 5
  • 32
  • 48
  • 6
    Be wary of the default locale! – tc. Nov 28 '12 at 15:43
  • 4
    For you Android users out there, I would like to point out that [Android documentation](http://developer.android.com/reference/java/util/Locale.html#default_locale) explicitly encourages the usage of `Locale.US` for machine readable input/output. – sulai Sep 02 '13 at 17:44
  • 2
    @Trengot Yes, unfortunately. Turkey is a good example. Combine this with Java's broken handling of default charsets (defaults to Latin on Windows instead of Unicode) and you'll find it's nearly always unsafe to use the default versions of methods that accept a charset or locale. You should almost always explicitly define them. – Stijn de Witt Jul 26 '15 at 13:34
  • Not sure Java's "default" charsets et al are "broken" per se but granted, defaulting to UTF-8 in lieu of overrides (which should be done always to be explicit) would have made better systems for junior programmers who commonly fail to understand charset concepts. – Darrell Teague May 29 '18 at 20:45
47

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();
    }
}
Hans Schreuder
  • 637
  • 5
  • 9
  • Not sure this is somehow any better an answer. Streams in this case are a single-threaded iterator like any other over all values and arguably less performant than a map lookup impl. Streams have more value in a multi-threaded context where, for example, parallel execution of a newline-separated text file can improve performance. – Darrell Teague Apr 15 '20 at 22:03
  • @DarrellTeague If you measure the nanosecond difference between the Streams solution and the map lookup solution then you will see a difference. However, I believe in the real world there will be no appreciable performance difference unless you have quite a large enum, which is an exception to the rule in my opinion. Plus the Streams approach is compact and readable, though I'm sure you could make the same argument for the map implementation as well – Flaom Jan 15 '21 at 20:59
39

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()
    ));
}
Radiodef
  • 35,285
  • 14
  • 78
  • 114
Patrick Arnesen
  • 1,018
  • 1
  • 9
  • 13
  • This variation is doing it correctly: `equalsIgnoreCase` is the way to go. +1 – Stijn de Witt Jul 26 '15 at 13:35
  • Like case insensivity but ... prefer Enums over (random) String assignments for keys and ... minor but iterating is less performant for such a possibly repetative lookup. Hence impl of EnumMap et al. – Darrell Teague Aug 13 '18 at 17:26
  • This does not work ! I changed the equalsIgnoreCase to equals for my purpose. The code failed even though both inputs to equals were exactly the same. – MasterJoe Nov 26 '18 at 20:49
36

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

raffian
  • 28,859
  • 25
  • 95
  • 164
Peter Lawrey
  • 498,481
  • 72
  • 700
  • 1,075
  • 1
    Case sensitive, not helping! – Murtaza Kanchwala Jun 28 '15 at 18:58
  • @MurtazaKanchwala Can you clarify your comment? What are you trying to do? – Peter Lawrey Jun 29 '15 at 10:18
  • 2
    Hi @PeterLawrey, I was tring to fetch an Enum from a String public enum ObjectType { PERSON("Person") public String parameterName; ObjectType(String parameterName) { this.parameterName = parameterName; } public String getParameterName() { return this.parameterName; } public static ObjectType fromString(String parameterName) { if (parameterName != null) { for (ObjectType objType : ObjectType.values()) { if (parameterName.equalsIgnoreCase(objType.parameterName)) { return objType; } } } return null; } } – Murtaza Kanchwala Jun 29 '15 at 17:45
31

My 2 cents here: using Java8 Streams + checking an exact string:

public enum MyEnum {
    VALUE_1("Super"),
    VALUE_2("Rainbow"),
    VALUE_3("Dash"),
    VALUE_3("Rocks");

    private final String value;

    MyEnum(String value) {
        this.value = value;
    }

    /**
     * @return the Enum representation for the given string.
     * @throws IllegalArgumentException if unknown string.
     */
    public static MyEnum fromString(String s) throws IllegalArgumentException {
        return Arrays.stream(MyEnum.values())
                .filter(v -> v.value.equals(s))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("unknown value: " + s));
    }
}

** EDIT **

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
Manu
  • 6,365
  • 4
  • 43
  • 58
  • 1
    Alternatively to allow you to write more readable `switch` blocks, you can `.orElse(null)` instead of `.orElseThrow()` so that you can code the exception throw in the `default` clause - and include more useful info when required. And to make it more lenient you could use `v -> Objects.equals(v.name, s == null ? "" : s.trim().toUpperCase())` – Adam May 10 '18 at 11:35
  • or just return the `Optional` from `findFirst()`, allowing the user to decide if he wants `.orElse(null)`, `orElseThrow()` or whatever.... – user85421 Aug 02 '18 at 20:58
  • 1
    Declaring a `public static MyEnum valueOf(String)` is actually a compilation error, since it's the same as the one implicitly defined, so the older version of your answer is actually better. ([jls](https://docs.oracle.com/javase/specs/jls/se11/html/jls-8.html#jls-8.9.3), [ideone](https://ideone.com/zNaviN)) – Radiodef Dec 23 '18 at 23:34
  • In my option it is better to avoid Exceptions and use Optional. Next to that we should void null and use Optional instead as well. – Hans Schreuder May 23 '19 at 10:57
  • Again, just remember that even if less or better looking code... a Stream implementation like this is just an iterator over all values versus a map lookup (less performant). – Darrell Teague Apr 15 '20 at 22:05
29

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.

Andrejs
  • 24,146
  • 10
  • 98
  • 92
  • 7
    sad part is, this returns a google Optional and not java Optional – javaProgrammer Aug 19 '16 at 00:02
  • True. Exoected though. Google and Netflix have great Java libs. Where there is overlap with Java catch-up classes implemented in newer versions inevitably causes trouble. Kind of have to be all in on one vendor lib. – Darrell Teague Aug 13 '18 at 17:30
16

You may need to this :

public enum ObjectType {
    PERSON("Person");

    public String parameterName;

    ObjectType(String parameterName) {
        this.parameterName = parameterName;
    }

    public String getParameterName() {
        return this.parameterName;
    }

    //From String method will return you the Enum for the provided input string
    public static ObjectType fromString(String parameterName) {
        if (parameterName != null) {
            for (ObjectType objType : ObjectType.values()) {
                if (parameterName.equalsIgnoreCase(objType.parameterName)) {
                    return objType;
                }
            }
        }
        return null;
    }
}

One More Addition :

   public static String fromEnumName(String parameterName) {
        if (parameterName != null) {
            for (DQJ objType : DQJ.values()) {
                if (parameterName.equalsIgnoreCase(objType.name())) {
                    return objType.parameterName;
                }
            }
        }
        return null;
    }

This will return you the Value by a Stringified Enum Name For e.g. if you provide "PERSON" in the fromEnumName it'll return you the Value of Enum i.e. "Person"

Murtaza Kanchwala
  • 2,296
  • 22
  • 33
13

Another way of doing this by using implicit static method name() of Enum. name will return the exact string used to create that enum which can be used to check against provided string:

public enum Blah {

    A, B, C, D;

    public static Blah getEnum(String s){
        if(A.name().equals(s)){
            return A;
        }else if(B.name().equals(s)){
            return B;
        }else if(C.name().equals(s)){
            return C;
        }else if (D.name().equals(s)){
            return D;
        }
        throw new IllegalArgumentException("No Enum specified for this string");
    }
}

Testing:

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

//it will print B  B

inspiration: 10 Examples of Enum in Java

Sameera Thilakasiri
  • 8,933
  • 8
  • 49
  • 80
Vikram
  • 187
  • 1
  • 2
  • 7
    This is essentially what `valueOf` does for you. This static method does not offer anything extra, exception et all. Then the if/else constructs are highly dangerous ... any new enum constant added will cause this method to break without change. – YoYo Sep 30 '12 at 18:01
  • Consider also this example of how we can use valueOf for doing a case insensitive lookup, or how we can avoid it's exception and employ aliases to provide alternative names: http://stackoverflow.com/a/12659023/744133 – YoYo Sep 30 '12 at 18:18
  • 2
    `name()` is not static. – nrubin29 Apr 21 '14 at 00:39
10

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();
   }
}
javabrew
  • 185
  • 3
  • 7
8

To add to the previous answers, and address some of the discussions around nulls and NPE I'm using Guava Optionals to handle absent/invalid cases. This works great for URI/parameter parsing.

public enum E {
    A,B,C;
    public static Optional<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 info on avoiding null with Optional: https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional

Radiodef
  • 35,285
  • 14
  • 78
  • 114
tom
  • 2,616
  • 12
  • 28
  • This is a really good answer for related patterns and use of Optional inside an Enum - leveraging the fact that Enums are classes too and thus can be decorated with methods, override methods, etc. It is a good case for Fluent-style programming also since nulls returned from methods make that construct buggy (NPE in unknown places in Fluent chains of method calls). – Darrell Teague Apr 15 '20 at 22:09
8

In Java 8 the static Map pattern is even easier and is my preffered method. If you want to use the Enum with Jackson you can override toString and use that instead of name, then annotate with @JsonValue

public enum MyEnum {
    BAR,
    BAZ;
    private static final Map<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);
    }
}
Novaterata
  • 3,327
  • 22
  • 39
  • Jackson is a JSON (JavaScript Object Notation) implementation. The original question had nothing to do with JSON. – Darrell Teague Apr 15 '20 at 22:06
  • The JSON part was just bonus stuff I found relevant at the time, since getting an Enum from a string is basically a type of deserialization and JSON / Jackson is probably the most popular serialization solution. – Novaterata Apr 16 '20 at 01:38
  • Understand but from moderation aspect - it did not contribute to the answering the OP's question so just trying to help set context there.JSON is indeed the way to go for converting objects to canonical form in Java with Jackson being a great library. – Darrell Teague Apr 17 '20 at 12:50
8

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 getDescription(String lang) method, for example:

String statusDescription = Status.valueOf("ACT").getDescription("en");
Ebraheem Alrabeea
  • 1,453
  • 3
  • 17
  • 31
  • 1
    Good example with pushing Enums further. Would have made the language-encoding using the standard static names and lookup in a Map but still... a good example of having an enum with different tags for what is essentially the same logical value. – Darrell Teague Apr 15 '20 at 22:11
6

O(1) method inspired from thrift generated code which utilize a hashmap.

public enum USER {
        STUDENT("jon",0),TEACHER("tom",1);

        private static final Map<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;
        }

}
Sisyphus
  • 756
  • 10
  • 15
  • 1
    Note the the zero (0) and one (1) identifiers are unnecessary. Enum values() method will return the members in the same order as coded. Thus the first entry will be ordinal zero, the second one, etc. – Darrell Teague Apr 15 '20 at 22:13
6
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;
}
Radiodef
  • 35,285
  • 14
  • 78
  • 114
Prasobh.Kollattu
  • 1,331
  • 1
  • 17
  • 31
5

Apache's commons-lang library has a static function org.apache.commons.lang3.EnumUtils.getEnum which will map a String to your Enum type. Same answer essentially as Geoffreys but why roll your own when it's out there in the wild already.

pjklauser
  • 1,086
  • 11
  • 13
  • 1
    Fair comment (DRY) but... while most of the Apache Commons stuff is great, I have found several bugs and anti-patterns myself in that base. Thus referring to say Joshua Bloch's implementation may be on stronger footing. Gets down to then having to review the Apache code to know what someone implemented. If it was say the famed Doug Leah who re-wrote Java concurrency ... then I would trust it implicitly. – Darrell Teague Apr 15 '20 at 22:16
5

What about?

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();
        }
    }
}
DCO
  • 1,142
  • 8
  • 19
4

java.lang.Enum defines several useful methods, which is available to all enumeration type in Java:

  • You can use name() method to get name of any Enum constants. String literal used to write enum constants is their name.
  • Similarly values() method can be used to get an array of all Enum constants from an Enum type.
  • And for the asked question, you can use valueOf() method to convert any String to Enum constant in Java, as shown below.
public class EnumDemo06 {
    public static void main(String args[]) {
        Gender fromString = Gender.valueOf("MALE");
        System.out.println("Gender.MALE.name() : " + fromString.name());
    }

    private enum Gender {
        MALE, FEMALE;
    }
}

Output:
Gender.MALE.name() : MALE

In this code snippet, valueOf() method returns an Enum constant Gender.MALE, calling name on that returns "MALE".

Radiodef
  • 35,285
  • 14
  • 78
  • 114
KNU
  • 2,304
  • 5
  • 22
  • 35
4

Adding on to the top rated answer, with a helpful utility...

valueOf() throws two different Exceptions in cases where it doesn't like its input.

  • IllegalArgumentException
  • NullPointerExeption

If your requirements are such that you don't have any guarantee that your String will definitely match an enum value, for example if the String data comes from a database and could contain old version of the enum, then you'll need to handle these often...

So here's a reusable method I wrote which allows us to define a default Enum to be returned if the String we pass doesn't match.

private static <T 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
}
user812786
  • 3,632
  • 3
  • 36
  • 49
lance.dolan
  • 2,286
  • 16
  • 29
3

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.

LuCio
  • 4,285
  • 1
  • 15
  • 29
1

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

Moesio
  • 2,782
  • 1
  • 24
  • 36
1

I was looking for an answer to find the "blah" name and not its value (not the text). base on @Manu (@Mano)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;
}

}

orly.sharon
  • 109
  • 1
  • 8
1

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

} }

Nitya Nand Pandey
  • 175
  • 1
  • 1
  • 11
0

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

Fastest way to get the name of enum is to create a map of enum text and value when the application start, and to get the name call the function Blah.getEnumName():

public enum Blah {
    A("text1"),
    B("text2"),
    C("text3"),
    D("text4");

    private String text;
    private HashMap<String, String> map;
    Blah(String text) {
    this.text = text;
    }

    public String getText() {
      return this.text;
    }

    static{
      createMapOfTextAndName();
    }

    public static void createMapOfTextAndName() {
        map = new HashMap<String, String>();
        for (Blah b : Blah.values()) {
             map.put(b.getText(),b.name());
        }
    }
    public static String getEnumName(String text) {
        return map.get(text.toLowerCase());
    } 
}
Bishal Jaiswal
  • 1,248
  • 10
  • 12
0

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
Gibolt
  • 24,018
  • 9
  • 129
  • 89
  • Do you think your answer will have a better home here? https://stackoverflow.com/questions/28548015/how-do-i-create-an-enum-from-a-string-in-kotlin – nabster May 05 '20 at 22:39
  • 1
    This is not a Kotlin question. – shinzou Jun 18 '20 at 10:29
  • 1
    This is similar to Js/jQuery. When Android devs search for a solution, they wind up looking for Java and then translating to Kotlin. This is a non-obvious, better solution than a direct translation. Search engines aren't going to stop prioritizing this solution any time soon, better to just help those devs quickly find a good solution. It is marked as Kotlin, Java devs can just skip over – Gibolt Jun 18 '20 at 16:06