Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get enum constant using its value [duplicate]

Tags:

java

enums

kotlin

Im trying to get enum using its value but it throws an error saying No enum constant. The eg code is in Kotlin but it is same in Java Thanks in advance.

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

Log:

Exception in thread "main" java.lang.IllegalArgumentException: No enum constant TaskAction.Un flag

like image 576
Sai Avatar asked Jan 04 '17 12:01

Sai


2 Answers

The valueOf method takes a string that should correspond the name of the enum constant. However, you extract the value of the enum and try to map that back to a constant. This does not work unless the value is equal to the name of the constant.

So your problem is that TaskAction.UN_FLAG.value returns "Un flag". Then you call TaskAction.valueOf("Un flag"), which cannot find any enum constant with the string you provided (because the name of the enum constant is UN_FLAG).

So basically: "Un flag" != "UN_FLAG"

Edit:

To fix the issue, I would create a function that finds the correct enum based on the value. I would place the function within the companion object of TaskAction. Like this:

companion object {
  fun from(s: String): TaskAction? = values().find { it.value == s }
}
like image 116
marstran Avatar answered Oct 21 '22 14:10

marstran


I changed my enum class to something like below, I added a static Map. Because there is no way it maps the value and name by itself. I thought this may help some.

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

Update:

Thank to @mfulton26 i simplified my code:

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

I even reduce the code to with the help of @marstran:

companion object {
    fun from(search: String): TaskAction =  requireNotNull(values().find { it.value == search }) { "No TaskAction with value $search" }
}
like image 34
Sai Avatar answered Oct 21 '22 14:10

Sai