Java example

How to convert a string to an enum in Java

7 min read Updated Sep 2026 Runs in an isolated runtime
Quick answer

Call the enum's built-in valueOf: Size.valueOf("MEDIUM") returns Size.MEDIUM. It needs the exact, case-sensitive constant name and throws IllegalArgumentException for anything else (and NullPointerException for null), so wrap user input in a lookup that returns an Optional. Compare the result with ==.

Every Java enum gets two static methods from the compiler: valueOf(String), which turns a constant's name into the constant, and values(), which returns all of them. They don't appear in the Javadoc for java.lang.Enum, which is why so many people go looking for them. valueOf is strict on purpose, so real code usually adds a forgiving lookup on top: case-insensitive, by a custom code, or returning Optional instead of throwing. The examples below use one small Size enum throughout. Each one runs on this page: hit Run, then edit the code and run it again.

1valueOf(): the exact constant nameRecommended

Size.valueOf(name) returns the constant whose name is exactly name: same case, no surrounding spaces. The generic form, Enum.valueOf(Size.class, name), does the same lookup when your code receives the enum type as a Class object. Both throw on a miss rather than returning null, which is right when a bad name means a bug, such as a typo in a config key you control.

Main.java

Output

Prints MEDIUM, true and LARGE. Then each bad input throws its own IllegalArgumentException: No enum constant Main.Size.medium, No enum constant Main.Size. MEDIUM (the leading space is part of the name it tried) and No enum constant Main.Size.XL. The message uses the enum's full name, Main.Size, because it is nested in Main. A null name is different: NullPointerException: Name is null. Catch both if the string can come from outside your program.

2Case-insensitive lookup that returns Optional

For input from users, URLs or files, you want "medium" and " Large " to work and a bad value to be an ordinary result, not an exception. Java has no built-in case-insensitive valueOf, so write a short helper that returns Optional. Loop over values() and compare with equalsIgnoreCase, or, for a helper that works with any enum, upper-case the input with Locale.ROOT and catch the exception. If you already use Guava or Apache Commons Lang, Enums.getIfPresent and EnumUtils.getEnumIgnoreCase do the same job.

Main.java

Output

The first six lines show the helper: "medium", " Large " and "extra_large" give Optional[MEDIUM], Optional[LARGE] and Optional[EXTRA_LARGE], while "XL" (a code, not a name: see the next section), the blank string and null all give Optional.empty. The caller then decides what a miss means: orElse(Size.MEDIUM) prints MEDIUM and orElseThrow() prints SMALL. The last three lines show why the generic helper passes Locale.ROOT. With a Turkish default locale, a bare toUpperCase() turns "medium" into MEDİUM with a dotted capital I, so valueOf throws No enum constant Main.Size.MEDİUM, while parseEnum still returns Optional[MEDIUM]. equalsIgnoreCase uses no locale at all, so parseSize prints true for the same string. strip() needs Java 11+ (use trim() on Java 8) and the no-argument orElseThrow() needs Java 10+.

3Look up by a code or label with a static map

Often the string you receive isn't the constant's name at all but some external value: a size code like "XL", an HTTP status, a database value. Store that value in a field, then build a static final map from it to the constant once, when the enum class loads. Each lookup is then a single get instead of a loop. The map has to be built in a static initializer that runs after the constants exist, which is what declaring it with Arrays.stream(values()) does.

Main.java

Output

Prints Optional[Extra large]: an Optional prints its value with toString(), which this enum overrides to return the label. Mapping to Size::name gives MEDIUM, an unknown code and null both give Optional.empty, and the round trip prints L true. The tempting shortcut, calling BY_CODE.put(code, this) in the constructor, doesn't compile: illegal reference to static field from initializer, because the constants are created before any other static field is set. The null check matters too, since the map from Collectors.toUnmodifiableMap (Java 10+) throws NullPointerException on get(null). A useful side effect: two constants with the same code fail at startup with IllegalStateException: Duplicate key S (attempted merging values SMALL and MINI).

4Which lookup should you use?

MethodMatchesOn no matchBest for
Size.valueOf(s)Exact name onlyThrows IllegalArgumentExceptionNames you wrote yourself: config keys, saved values
Enum.valueOf(Size.class, s)Exact name onlyThrows IllegalArgumentExceptionGeneric code that receives the enum class
values() + equalsIgnoreCaseName, any caseOptional.empty()User input for one enum
valueOf(s.toUpperCase(Locale.ROOT)) in try/catchName, any caseOptional.empty()One helper shared by every enum
static Map<String, Size>Your own code or labelOptional.empty()External values like "XL" or 404
Size.values()[i]Position (ordinal)Throws ArrayIndexOutOfBoundsExceptionRarely: ordinals change when constants are reordered

5Loop over every constant: values(), name() and toString()

Size.values() returns every constant in declaration order, so a for-each loop over it is how you iterate an enum. Each constant has three ways to describe itself: ordinal() is its position, name() is the identifier exactly as declared, and toString() returns the name too unless you override it. That difference matters here, because valueOf only ever reads name().

Main.java

Output

The loop prints one row per constant, from 0 SMALL Small to 3 EXTRA_LARGE Extra large. valueOf(Size.LARGE.name()) round-trips to Large, but valueOf(Size.LARGE.toString()) throws No enum constant Main.Size.Large: store and send name(), which is final and can't be overridden, and keep toString() for display. Arrays.toString uses toString(), so it prints [Small, Medium, Large, Extra large], and length is 4. values() == values() is false because each call returns a fresh copy of the array. EnumSet.range gives [Medium, Large, Extra large], and the EnumMap prints {Small=12, Large=4, Extra large=0}: declaration order, not the order the entries were added.

6Compare with == and switch on an enum

Each enum constant is a single object for the life of the program, so == and equals() give the same answer, and Enum.equals is itself implemented as ==. Prefer ==: it can't throw when the left side is null, and the compiler rejects comparisons between two different enum types. Strings are the opposite case, where == is the wrong test (see compare strings in Java).

To branch on a constant, use switch. The arrow-form switch expression (Java 14+) returns a value and needs no default when every constant is listed, and Java 21+ adds case null.

Main.java

Output

Prints true twice, then false twice for the null comparisons, which neither throw. Only missing.equals(...) throws a NullPointerException. The switch prices print SMALL costs 18 through EXTRA_LARGE costs 22, and describe prints small, XL, ships separately and no size chosen. Without case null, price(null) throws, like every switch before Java 21. Delete the EXTRA_LARGE case from price and it stops compiling: the switch expression does not cover all possible input values. That check is a reason to list every constant instead of reaching for default: adding a constant later points you at every switch that needs updating. Likewise, Size.LARGE == Color.RED fails with incomparable types: Main.Size and Main.Color, while Size.LARGE.equals(Color.RED) compiles and quietly returns false.

Frequently asked questions

How do I get an enum value from a string in Java?

Call the enum's generated valueOf method: Size.valueOf("MEDIUM") returns Size.MEDIUM. The string must match the constant's name exactly, including case, or it throws IllegalArgumentException: No enum constant Main.Size.medium. A null string throws NullPointerException: Name is null. For input you don't control, wrap the lookup in a helper that returns Optional<Size>.

Should I compare Java enums with == or equals()?

Use ==. There is only ever one instance of each constant, so both give the same result, but == is null-safe (null == Size.LARGE is false, while missing.equals(Size.LARGE) throws NullPointerException) and it is checked at compile time: Size.LARGE == Color.RED fails with incomparable types, where equals compiles and returns false.

How do I loop over all values of an enum?

Use a for-each loop over Size.values(), which returns the constants in declaration order. EnumSet.allOf(Size.class) gives the same constants as a Set, and EnumSet.range(Size.MEDIUM, Size.EXTRA_LARGE) a slice of them. To get the names as a list, Arrays.stream(Size.values()).map(Enum::name).toList() prints [SMALL, MEDIUM, LARGE, EXTRA_LARGE] (toList() needs Java 16+).

How do I make Enum.valueOf case-insensitive?

There is no built-in option. Either loop over values() and return the constant whose name().equalsIgnoreCase(input), or call valueOf(input.strip().toUpperCase(Locale.ROOT)) inside a try/catch. Always pass Locale.ROOT: with a Turkish default locale, "medium".toUpperCase() is MEDİUM, which matches no constant.

What is the difference between name() and toString() on an enum?

name() returns the identifier exactly as declared and is final, so it always works with valueOf. toString() returns the same string by default, but an enum can override it to return a display label. After overriding it to "Large", Size.valueOf(Size.LARGE.toString()) throws No enum constant Main.Size.Large. Persist and transmit name() (or your own code field) and use toString() for display.

How do I convert an int to an enum in Java?

If the int is the ordinal, index into the array: Size.values()[2] is LARGE, and an index past the end throws ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4. Ordinals shift when someone reorders or inserts constants, so don't store them. For stable numbers such as HTTP status codes, give the enum an int field and look it up in a static map, as in section 3.

Run it yourself

Open any of these in the full Java editor to tweak, run and share.

Java playground