如何在Kotlin中获得泛型参数类?

我需要能够在运行时告诉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) } 

Kotlin泛型共享了Java在编译时被删除的特性,因此,在运行时,这些列表不再携带必要的信息来执行您所要求的操作。 这是一个例外,如果你写一个内联函数,使用reified类型。 例如,这将工作:

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

你可以使用带有特定类型参数的inline函数来做到这一点:

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

(可运行的演示,包括如何检查when语句中的类型)

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

在JVM上,泛型类的类型参数在运行时被擦除,并且基本上没有办法从任意List<T>检索它们(例如列表传递到非内联函数List<T>T是在编译时不知道每个调用,并在运行时擦除)

如果您需要更多地控制函数内的实参类型参数,您可能会发现这个问答有用。