Kotlin:如何检查枚举是否包含给定的字符串而不会弄乱异常?

Mak*_*dov 13 kotlin

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

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

mfu*_*n26 29

enumContains

您可以创建一个enumContains类似的功能猎犬答案,但使用具体化的类型参数来代替.

您无法在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}
}
Run Code Online (Sandbox Code Playgroud)

科特林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}
}
Run Code Online (Sandbox Code Playgroud)

用法

enumContains<MyEnum>("some string") // returns true or false
Run Code Online (Sandbox Code Playgroud)

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 }
}
Run Code Online (Sandbox Code Playgroud)

科特林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 }
}
Run Code Online (Sandbox Code Playgroud)

用法

enumValueOfOrNull<MyEnum>("some string")
Run Code Online (Sandbox Code Playgroud)

  • 是的,使用`reified`要好得多(在KClass上有一个扩展功能不是很漂亮!).在一个半相关旁注,用`enumConstants`一起,1.1带来的是[反射好东西]一整袋(https://github.com/JetBrains/kotlin/commit/ed1490dbc43f88696f82e5307df43269ecbb32b1)! (2认同)

Jan*_*son 6

您可以只values使用您的枚举数组,并在其中使用包含。例如:

Planets.values().map { it.name }.contains("EARTH")
Run Code Online (Sandbox Code Playgroud)

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

如果要按其值查找枚举,请查看反向查找枚举。

编辑:

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

Planets.values().any { it.name == "EARTH" }
Run Code Online (Sandbox Code Playgroud)

  • 我可能会简化为`Planets.values()。any {it.name ==“ EARTH”}`(您希望它在找到匹配项后就停止查找,而不是查看整个列表) (9认同)