通过Kotlin中的反射获取枚举值

时间:2018-09-13 14:30:54

标签: reflection enums kotlin

您如何在Kotlin中重写以下Java代码?

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

有问题的行是Enum.valueOf(enumClz, enumValue)

从IntelliJ IDE / Android Studio自动转换会产生以下Enum.valueOf<Enum>(enumClz, enumValue),但是Kotlin中没有这样的方法Enum.valueOf

强制Kotling使用java.lang.Enumjava.lang.Enum.valueOf<Enum>(enumClz, enumValue)。通用绑定One type argument expected for class Enum<E: Enum<E>>上的编译错误。

将类型实参添加为java.lang.Enum.valueOf<Enum<*>>(enumClz, enumValue)会产生另一个错误:Type argument is not within its bounds. Expected: Enum<Enum<*>!>! Found: Enum<*>

1 个答案:

答案 0 :(得分:0)

我发现最好的方法是为枚举创建接口,并将其转换为类型化的枚举:

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

这不是最优雅的方法,但它可以工作。如果我找到更好的解决方案,请更新此消息。