Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum.valueOf in Kotlin

Tags:

Is there a way to make something like this work in Kotlin without the reflection?

inline fun <reified T : kotlin.Enum<T>> safeValueOf(type: String?): T? {     return java.lang.Enum.valueOf(T::class.java, type) } 

The example below doesn't compile due to:

Type parameter bound for T in inline fun <reified T : kotlin.Enum<T>> safeValueOf(type: kotlin.String?): T? is not satisfied: inferred type TestEnum? is not a subtype of kotlin.Enum<TestEnum?>

enum class TestEnum  fun main() {     val value: TestEnum? = safeValueOf("test") } 
like image 799
AndroidEx Avatar asked Feb 27 '16 07:02

AndroidEx


People also ask

How do I get Kotlin enum value?

To get an enum constant by its string value, you can use the function valueOf() on the Enum class. It helps us to get enum from a String value in Kotlin.

What does valueOf do in enum?

valueOf. Returns the enum constant of the specified enum type with the specified name. The name must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)


2 Answers

Your function works if you specify the type parameter value explicitly:

val value = safeValueOf<TestEnum>("test") 

The original code is supposed to work as well, but doesn't work because of a bug in the type inference implementation: https://youtrack.jetbrains.com/issue/KT-11218

like image 191
yole Avatar answered Sep 20 '22 14:09

yole


Crash-safe 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: IllegalArgumentException) {         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: IllegalArgumentException) {         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 
like image 39
Gibolt Avatar answered Sep 18 '22 14:09

Gibolt