【问题标题】:Enum.valueOf in KotlinKotlin 中的 Enum.valueOf
【发布时间】:2016-02-27 07:01:08
【问题描述】:

有没有办法在没有反射的情况下在 Kotlin 中进行类似的工作?

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

以下示例无法编译,原因是:

inline fun &lt;reified T : kotlin.Enum&lt;T&gt;&gt; safeValueOf(type: kotlin.String?): T? 中为 T 绑定的类型参数 不满意:推断类型TestEnum? 不是kotlin.Enum&lt;TestEnum?&gt; 的子类型

enum class TestEnum

fun main() {
    val value: TestEnum? = safeValueOf("test")
}

【问题讨论】:

  • 如果您明确指定类型参数值,您的函数将起作用:val value = safeValueOf&lt;TestEnum&gt;("test")
  • 为什么不直接使用 valueOf 的 Kotlin 实现?
  • @soon 我想扩展valueOf 的功能并将其与不同的枚举类型一起使用
  • 请问这是safeValueOf吗?这仍然会引发异常
  • @charlie_pl 问题标题并没有真正说明安全性。当时的问题是使这个构造工作,并且,正如您正确指出的那样,safeValueOf 在这里并不安全,因为它只是手头问题的一个最小示例。但是您可以很容易地想象如何从这里使它变得安全。

标签: java enums kotlin


【解决方案1】:

如果您明确指定类型参数值,您的函数将起作用:

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

原始代码应该也可以工作,但由于类型推断实现中的错误而无法工作:https://youtrack.jetbrains.com/issue/KT-11218

【讨论】:

    【解决方案2】:

    防撞解决方案

    创建一个扩展,然后调用valueOf&lt;MyEnum&gt;("value")。如果类型无效,你会得到 null 并且必须处理它

    inline fun <reified T : Enum<T>> valueOf(type: String): T? {
        return try {
            java.lang.Enum.valueOf(T::class.java, type)
        } catch (e: IllegalArgumentException) {
            null
        }
    }
    

    或者,您可以设置默认值,调用valueOf&lt;MyEnum&gt;("value", MyEnum.FALLBACK),并避免空响应。您可以扩展您的特定枚举以使默认值为自动

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

    或者如果你想要两个,做第二个:

    inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default
    

    【讨论】:

      【解决方案3】:

      我通常会在枚举中添加类似这样的内容:

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

      这将是一个干净的电话

      val value = TestEnum.from("test")
      

      当然你可以让它返回null

      【讨论】:

        【解决方案4】:

        从 Kotlin 1.1 开始,可以使用 enumValues() 和 enumValueOf() 函数以通用方式访问枚举类中的常量:

        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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-11-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-25
          相关资源
          最近更新 更多