0Day Forums
Get Enum value by reflection in Kotlin - Printable Version

+- 0Day Forums (https://zeroday.vip)
+-- Forum: Coding (https://zeroday.vip/Forum-Coding)
+--- Forum: Kotlin (https://zeroday.vip/Forum-Kotlin)
+--- Thread: Get Enum value by reflection in Kotlin (/Thread-Get-Enum-value-by-reflection-in-Kotlin)



Get Enum value by reflection in Kotlin - ashelyfoqj - 07-20-2023

How would you rewrite the following Java code in Kotlin?

@SuppressWarnings({ "unchecked", "rawtypes" })
static Object getEnumValue(String enumClassName, String enumValue) throws ClassNotFoundException {
Class<Enum> enumClz = (Class<Enum>)Class.forName(enumClassName);
return Enum.valueOf(enumClz, enumValue);
}

The problematic line is `Enum.valueOf(enumClz, enumValue)`

The automatic conversion from IntelliJ IDE/Android Studio yields the following `Enum.valueOf<Enum>(enumClz, enumValue)`, however there's no such method `Enum.valueOf` in Kotlin.

Forcing Kotling to use `java.lang.Enum`: `java.lang.Enum.valueOf<Enum>(enumClz, enumValue)`. Compile error on the generic binding `One type argument expected for class Enum<E: Enum<E>>`.

Adding the type argument as `java.lang.Enum.valueOf<Enum<*>>(enumClz, enumValue)` yields a different error: `Type argument is not within its bounds. Expected: Enum<Enum<*>!>! Found: Enum<*>`.




RE: Get Enum value by reflection in Kotlin - bendees542183 - 07-20-2023

You could do this in following way, of course you should probably do some additional checks for passed parameters but this should be what you are looking for:

fun getEnumValue(enumClassName: String, enumValue: String): Any {
val enumClz = Class.forName(enumClassName).enumConstants as Array<Enum<*>>
return enumClz.first { it.name == enumValue }
}


Also there is [enumValueOf][1] function but there you need to know actual enum type so not sure it helps, anyway here is how you could use that:

enum class SomeEnum{
FIRST, SECOND
}
val enumMember = enumValueOf<SomeEnum>("FIRST")


[1]:

[To see links please register here]




RE: Get Enum value by reflection in Kotlin - kusti377928 - 07-20-2023

The best way I have found is to create an interface for the enums, converting them in typed enums:

/**
* Allow to search enums by type
*/
interface TypedEnum<T> {
fun value(): T

companion object {

/**
* Get the value of a typed enum
* @param enumValues array - You can get it with Enum.values()
* @param enumValue to search
* @param defaultValue to return if not found
* @return enum type or default value if not found or first enum value if default value not set
*/
fun <T, E : TypedEnum<T>> getEnumValue(enumValues: Array<E>, enumValue: T, defaultValue: E? = null): E {
try {
return enumValues.first { it.value()?.equals(enumValue) ?: false}
} catch (nsee: NoSuchElementException) {
// Log.e("TYPED_ENUM", "Exception converting value to enum type: $nsee")
}
return defaultValue ?: enumValues.first()
}
}

}

enum class TypeInt: TypedEnum<Int> {
TYPE_1 { override fun value() = 1 },
TYPE_2 { override fun value() = 2 },
TYPE_3 { override fun value() = 3 },
}

enum class TypeString: TypedEnum<String> {
TYPE_1 { override fun value() = "1" },
TYPE_2 { override fun value() = "2" },
TYPE_3 { override fun value() = "3" },
}

@Test
fun getEnumValue_valueExistInt() {

val value = TypedEnum.getEnumValue(TypeInt.values(), 2)
assertEquals(TypeInt.TYPE_2, value)
}

@Test
fun getEnumValue_valueExistString() {

val value = TypedEnum.getEnumValue(TypeString.values(), "2")
assertEquals(TypeString.TYPE_2, value)
}

@Test
fun getEnumValue_valueNotExist() {

val value = TypedEnum.getEnumValue(TypeInt.values(), 0)
assertEquals(TypeInt.TYPE_1, value)
}

@Test
fun getEnumValue_valueNotExistReturnDefault() {

val value = TypedEnum.getEnumValue(TypeInt.values(), 0, TypeInt.TYPE_3)
assertEquals(TypeInt.TYPE_3, value)
}


It is not the most elegant way, but it works. If I find a better solution I update this message.