使用枚举值获取枚举常量

9

我试图通过其值获取枚举,但是它会抛出一个错误,显示没有枚举常量。这个例子的代码是Kotlin,但Java中也一样。谢谢。

import java.util.*

enum class TaskAction constructor(val value: String) {
    ARCHIVE("Archive"), UN_FLAG("Un flag"), FLAG("Flag"), REDO("Redo"),
    READY("Ready"), EDIT("Edit"), DND("dnd"), DELETE("Delete"),
    IN_PROGRESS("In progress"), DONE("Done");
}


fun main(args: Array<String>) {
    showSomeThing(TaskAction.UN_FLAG.value)
}

fun showSomeThing(enum: String) {
    println(TaskAction.valueOf(enum))
}

日志:

主线程中的异常java.lang.IllegalArgumentException: No enum constant TaskAction.Un flag


“eg代码是用Kotlin编写的,但在Java中也是相同的。” - 在Java中什么是相同的?考虑到写Java的人比写Kotlin的人更多,我强烈建议您写一个Java问题而不是Kotlin问题... - Jon Skeet
也许可以省略 constructor。请参考以下链接进行比较:https://kotlinlang.org/docs/reference/enum-classes.html - Roel Strolenberg
https://dev59.com/SHNA5IYBdhLWcg3wIqLr#1080914 - Januson
1
对于像这样的任务——您想通过某些属性而不是它们声明的名称来查找枚举值——有两种标准解决方案:(1)提供从值到名称的自动转换(例如大写并用下划线替换空格)(2)使用静态Map - Ole V.V.
2个回答

20
valueOf方法需要传递一个字符串,该字符串应对应于枚举常量的名称。但是,您提取了枚举的值并尝试将其映射回常量。除非该值等于常量的名称,否则这样做是行不通的。

因此,您的问题在于TaskAction.UN_FLAG.value返回"Un flag"。然后,您调用TaskAction.valueOf("Un flag"),它无法找到任何与提供的字符串相匹配的枚举常量(因为枚举常量的名称是UN_FLAG)。

基本上就是:"Un flag" != "UN_FLAG"

编辑:

要解决此问题,我会创建一个函数来根据值查找正确的枚举。我会将该函数放置在TaskAction的伴随对象中。像这样:

companion object {
  fun from(s: String): TaskAction? = values().find { it.value == s }
}

感谢@marstran,我知道"Un flag" != "UN_FLAG"。我正在寻找解决方案而不是解释。 - Sai
2
@SaiKiran 请查看编辑。 - marstran

6
我将我的枚举类更改为以下的样子,我添加了一个静态 Map。因为它本身没有办法映射值和名称。我认为这可能会有所帮助。
    enum class TaskAction constructor(val value: String) {
    ARCHIVE("Archive"), UN_FLAG("Un flag"), FLAG("Flag"), REDO("Redo"),
    READY("Ready"), EDIT("Edit"), DND("dnd"), DELETE("Delete"),
    IN_PROGRESS("In progress"), DONE("Done");

    companion object {
        private val lookup = HashMap<String, TaskAction>()

        init {
            TaskAction.values().map { lookup.put(it.value, it) }
        }

        fun getFromValue(value: String):TaskAction {
            return lookup[value]!!
        }
    }
}

更新:

感谢 @mfulton26,我简化了我的代码:

enum class TaskAction constructor(val value: String) {
    ARCHIVE("Archive"), UN_FLAG("Un flag"), FLAG("Flag"), REDO("Redo"),
    READY("Ready"), EDIT("Edit"), DND("dnd"), DELETE("Delete"),
    IN_PROGRESS("In progress"), DONE("Done");

    companion object {
        private val lookup = values().associateBy(TaskAction::value)
        fun fromValue(value: String):TaskAction = requireNotNull(lookup[value]) { "No TaskAction with value $value" }
    }
}

在@marstran的帮助下,我甚至将代码压缩到了:

companion object {
    fun from(search: String): TaskAction =  requireNotNull(values().find { it.value == search }) { "No TaskAction with value $search" }
}

2
  1. fromValue 可能比 getFromValue 更好的名称。
  2. lookup 可以简单地初始化为 private val lookup = values().associateBy(TaskAction::value)
  3. 你可能想抛出一个 IllegalArgumentException 而不是一个 KotlinNullPointerException。例如:return requireNotNull(lookup[value]) { "No TaskAction with value $value" }
- mfulton26

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接