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. |