简体   繁体   中英

Enum.valueOf in Kotlin

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

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

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

Since Kotlin 1.1, it's possible to access the constants in an enum class in a generic way, using the enumValues() and enumValueOf() functions:

enum class RGB { RED, GREEN, BLUE }

inline fun <reified T : Enum<T>> printAllValues() {
    print(enumValues<T>().joinToString { it.name })
}

printAllValues<RGB>() // prints RED, GREEN, BLUE

https://kotlinlang.org/docs/reference/enum-classes.html#working-with-enum-constants

I would typically add something like this to enum:

companion object {
    fun from(type: String?): TestEnum = values().find { it.name == type } ?: DEFAULT
}

this would make a clean call

val value = TestEnum.from("test")

of course you can make it return null

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM