【问题标题】:Kotlin: How to check if enum contains a given String without messing with Exceptions?Kotlin:如何检查枚举是否包含给定的字符串而不会弄乱异常?
【发布时间】:2017-01-25 05:29:00
【问题描述】:

为什么枚举类(以及Java)中没有contains 方法?以及如何优雅地实现它?现在我正在使用这种丑陋的方法:

val contains: Boolean = 
    try {
        MyEnum.valueOf("some string")
        true
    } catch (e: IllegalArgumentException) {
        false
    }

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    enumContains

    您可以创建一个类似于Hound DoganswerenumContains 函数,但改用reified type parameters

    您无法在 Kotlin 1.0 中创建独立于 JVM 的解决方案,但您可以在 Kotlin 1.1 中使用 enumValues

    科特林 1.1

    /**
     * Returns `true` if enum T contains an entry with the specified name.
     */
    inline fun <reified T : Enum<T>> enumContains(name: String): Boolean {
        return enumValues<T>().any { it.name == name}
    }
    

    科特林 1.0

    /**
     * Returns `true` if enum T contains an entry with the specified name.
     */
    inline fun <reified T : Enum<T>> enumContains(name: String): Boolean {
        return T::class.java.enumConstants.any { it.name == name}
    }
    

    用法

    enumContains<MyEnum>("some string") // returns true or false
    

    enumValueOfOrNull

    如果您还需要实际的枚举条目,那么您可以考虑创建一个 enumValueOfOrNull 函数。

    科特林 1.1

    /**
     * Returns an enum entry with the specified name or `null` if no such entry was found.
     */
    inline fun <reified T : Enum<T>> enumValueOfOrNull(name: String): T? {
        return enumValues<T>().find { it.name == name }
    }
    

    科特林 1.0

    /**
     * Returns an enum entry with the specified name or `null` if no such entry was found.
     */
    inline fun <reified T : Enum<T>> enumValueOfOrNull(name: String): T? {
        return T::class.java.enumConstants.find { it.name == name }
    }
    

    用法

    enumValueOfOrNull<MyEnum>("some string")
    

    【讨论】:

    • 是的,使用reified 会更好(在 KClass 上具有扩展功能不是很漂亮!)。在半相关的旁注中,与enumConstants 一起,1.1 带来了一整袋reflection goodies
    【解决方案2】:

    您可以使用枚举的 values 数组并在其上使用 contains。例如:

    Planets.values().map { it.name }.contains("EARTH")
    

    但为此,您需要有正确的字符串值,以便在搜索之前将其大写。

    如果您想通过枚举值查找枚举,请查看Reverse Lookup 中的枚举。

    编辑:

    正如@JamesBassett 建议的那样,您可以对其进行优化以在找到匹配项后停止查找。

    Planets.values().any { it.name == "EARTH" }
    

    【讨论】:

    • 我可能会简化为Planets.values().any { it.name == "EARTH" }(您希望它在找到匹配项后停止查找,而不是查看整个列表)
    【解决方案3】:

    你可以这样做:

    fun <T : Enum<*>> KClass<T>.contains(value: String): Boolean {
        return this.java.enumConstants.any { it.name == value }
    }
    
    MyEnum::class.contains("some string")
    

    【讨论】:

      猜你喜欢
      • 2011-06-23
      • 2014-08-09
      • 2012-08-30
      • 1970-01-01
      • 2017-03-28
      • 2011-06-03
      • 1970-01-01
      • 2018-06-14
      • 1970-01-01
      相关资源
      最近更新 更多