How do I create an enum from a string in Kotlin?
KotlinKotlin 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