【问题标题】:How to get generic param class in Kotlin?如何在 Kotlin 中获取通用参数类?
【发布时间】:2017-04-03 12:36:06
【问题描述】:

我需要能够在运行时判断 kotlin 集合的泛型类型。我该怎么做?

val list1 = listOf("my", "list")
val list2 = listOf(1, 2, 3)
val list3 = listOf<Double>()

/* ... */

when(list.genericType()) {
    is String -> handleString(list)
    is Int -> handleInt(list)
    is Double -> handleDouble(list)
}

【问题讨论】:

  • 你的目标是JVM还是js?在 JVM 上,除了 kotlin refied 类型之外,还有一些反射魔法,但在 js 后端,你可以依赖的只是 refied 类型。

标签: kotlin


【解决方案1】:

Kotlin 泛型具有 Java 在编译时被擦除的特性,因此,在运行时,这些列表不再包含执行您所要求的操作所需的信息。例外情况是,如果您使用具体类型编写内联函数。例如,这会起作用:

inline fun <reified T> handleList(l: List<T>) {
    when (T::class) {
        Int::class -> handleInt(l)
        Double::class -> handleDouble(l)
        String::class -> handleString(l)
    }
}

fun main() {
    handleList(mutableListOf(1,2,3))
}

不过,内联函数在每个调用站点都会扩展,并且会弄乱您的堆栈跟踪,因此您应该谨慎使用它们。

不过,根据您要实现的目标,还有一些替代方案。您可以使用密封类在元素级别实现类似的目标:

sealed class ElementType {
    class DoubleElement(val x: Double) : ElementType()
    class StringElement(val s: String) : ElementType()
    class IntElement(val i: Int) : ElementType()
}

fun handleList(l: List<ElementType>) {
    l.forEach {
        when (it) {
            is ElementType.DoubleElement -> handleDouble(it.x)
            is ElementType.StringElement -> handleString(it.s)
            is ElementType.IntElement -> handleInt(it.i)
        }
    }
}

【讨论】:

    【解决方案2】:

    您可以使用inline functions with reified type parameters 来做到这一点:

    inline fun <reified T : Any> classOfList(list: List<T>) = T::class
    

    (runnable demo, including how to check the type in a when statement)

    此解决方案仅限于 T 的实际类型参数在编译时已知的情况,因为 inline 函数在编译时进行转换,并且编译器将其 reified 类型参数替换为实际类型在每个呼叫站点。

    在 JVM 上,泛型类的类型参数在运行时被删除,基本上没有办法从任意的List&lt;T&gt; 中检索它们(例如,作为List&lt;T&gt; 传递给非内联函数的列表@ -- @ 987654333@ 在每次调用的编译时是未知的,在运行时被擦除)

    如果您需要对函数内的具体类型参数进行更多控制,您可能会发现this Q&A 很有用。

    【讨论】:

    • 您的可运行演示在“reified T”上缺少“: Any”。
    猜你喜欢
    • 1970-01-01
    • 2019-02-26
    • 1970-01-01
    • 2016-07-15
    • 2018-07-26
    • 1970-01-01
    • 2021-03-14
    • 2018-10-29
    • 1970-01-01
    相关资源
    最近更新 更多