Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get enum value of raw type from an enum class and a string in kotlin

I have the following code in java:

Enum getEnumValue(Class<?> enumClass, String value) {
    return Enum.valueOf((Class<Enum>) enumClass, value);
}

How to rewrite this in Kotlin?

Update

enumValueOf<>() function is not applicable in this case because I don't know the actual type parameter, I only have a Class<?> object with unknown type (Class<*> in kotlin) and a name string. The Class is known to be enum: Class.isEnum returns true. Using these two inputs, the java code above allows to obtain the value of the enum with a raw type. That's just what I need because I'm not interested in the specific type of the enum. But I can't figure out how to get the same result in kotlin.

like image 215
Eugene Avatar asked Sep 26 '17 00:09

Eugene


People also ask

How do I get the enum from string in Kotlin?

Example: Lookup enum by string value We then use the enum TextStyle's valueOf() method to pass the style and get the enum value we require. Since, valueOf() takes case-senstitive string value, we had to use toUpperCase() method to convert the given string to upper case.

What is the method to convert an enum type to a string type?

There are two ways to convert an Enum to String in Java, first by using the name() method of Enum which is an implicit method and available to all Enum, and second by using toString() method.


2 Answers

Here's a pure Kotlin version:

@Suppress("UNCHECKED_CAST")
fun getEnumValue(enumClass: Class<*>, value: String): Enum<*> {
    val enumConstants = enumClass.enumConstants as Array<out Enum<*>>
    return enumConstants.first { it.name == value }
}

Note that it's not as efficient as the Java version. java.lang.Enum.valueOf uses a cached data structure while this version needs to create a new array to iterate over. Also this version is O(n) wheras the Java version is O(1) as it uses a dictionary under the hood.

There is an open issue in the Kotlin bug tracker to support the same code as in Java which is scheduled for 1.3.

Here's a really ugly hack to workaround the generic type issue:

private enum class Hack

fun getEnumValue(enumClass: Class<*>, value: String): Enum<*> {
    return helper<Hack>(enumClass, value)
}

private fun <T : Enum<T>>helper(enumClass: Class<*>, value: String): Enum<*> {
    return java.lang.Enum.valueOf(enumClass as Class<T>, value)
}

A quick test shows that it's working but I wouldn't rely on it.


If the generic type is available, you can use the built-in function enumValueOf (see also http://kotlinlang.org/docs/reference/enum-classes.html#working-with-enum-constants):

enum class Color {
    Red, Green, Blue
}

enumValueOf<Color>("Red")
like image 67
Kirill Rakhman Avatar answered Sep 30 '22 17:09

Kirill Rakhman


You can use below Kotlin code in your class for java code:

Kotlin function code:

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

Example:

internal enum class MyEnum {
    MIDDLE_NAME
}
internal enum class MyEnumTwo {
    FIRST_NAME
}
internal enum class MyEnumThree {
    LAST_NAME
}


private fun demo(){

    System.out.println(getEnumValue<MyEnumTwo>("FIRST_NAME"))
    System.out.println(getEnumValue<MyEnum>("MIDDLE_NAME"))
    System.out.println(getEnumValue<MyEnumThree>("LAST_NAME"))

}

Output:

System.out: FIRST_NAME

System.out: MIDDLE_NAME

System.out: LAST_NAME

Old answer:

fun getEnumValue(enumClass:Class<>, value:String):Enum<> { return Enum.valueOf>>(enumClass as Class>>, value) }

like image 32
pRaNaY Avatar answered Sep 30 '22 17:09

pRaNaY