How do I create an enum from a string in Kotlin?

Kotlin

Kotlin Problem Overview


I have an enum with some instances Foo and Bar. If I have a string "Foo", how can I instantiate a Foo enum from that? In C# it would be Enum.Parse(...), is there an equivalent in Kotlin?

Currently, the best I have found is to create a factory that switches on all possible strings, but that is error prone and performs poorly for large enumerations.

Kotlin Solutions


Solution 1 - Kotlin

Kotlin enum classes have "static" function valueOf to get enum entry by string(like Java enums). Additionally they have "static" function values to get all enum entries. Example:

enum class MyEnum {
  Foo, Bar, Baz
}

fun main(args : Array<String>) {
  println(MyEnum.valueOf("Foo") == MyEnum.Foo)
  println(MyEnum.valueOf("Bar") == MyEnum.Bar)
  println(MyEnum.values().toList())
}

Solution 2 - Kotlin

As bashor suggested, use MyEnum.valueOf() but please have in mind that it throws an exception if value can't be found. I recommend using:

enum class MyEnum {
  Foo, Bar, Baz
}

try {
   myVar = MyEnum.valueOf("Qux")
} catch(e: IllegalArgumentException) {
   Log.d(TAG, "INVALID MyEnum value: 'Qux' | $e")
}

Solution 3 - Kotlin

Would do it like

enum class MyEnum {
  Foo, Bar, Baz
}

val value = MyEnum.values().firstOrNull {it.name == "Foo"} // results to MyEnum.Foo

Solution 4 - Kotlin

Reusable Exception Safe Solution

The default solution in Kotlin will throw an exception. If you want a reliable solution that works statically for all enums, try this!

Now just call valueOf<MyEnum>("value"). If the type is invalid, you'll get null and have to handle it, instead of an exception.

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

Solution 5 - Kotlin

If you want to create an enum value from one of its parameters, instead of the name, this funny code does a pretty decent job:

inline fun <reified T : Enum<T>, V> ((T) -> V).find(value: V): T? {
    return enumValues<T>().firstOrNull { this(it) == value }
}

This can be used like this:

enum class Algorithms(val string: String) {
    Sha1("SHA-1"),
    Sha256("SHA-256"),
}

fun main() = println(
    Algorithms::string.find("SHA-256")
            ?: throw IllegalArgumentException("Bad algorithm string: SHA-256")
)

This will print Sha256

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMicah ZoltuView Question on Stackoverflow
Solution 1 - KotlinbashorView Answer on Stackoverflow
Solution 2 - KotlinPaul ArdeleanuView Answer on Stackoverflow
Solution 3 - KotlinNordmeyerView Answer on Stackoverflow
Solution 4 - KotlinGiboltView Answer on Stackoverflow
Solution 5 - KotlinsquirrelView Answer on Stackoverflow