我需要能够在运行时告诉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)
}
Run Code Online (Sandbox Code Playgroud)
pdp*_*dpi 10
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))
}
Run Code Online (Sandbox Code Playgroud)
但是,内联函数会在每个调用站点进行扩展,并且会混乱堆栈跟踪,因此您应该谨慎使用它们.
但是,根据你想要达到的目标,有一些替代方案.您可以使用密封类在元素级别实现类似的功能:
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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用inline
带有reified
类型参数的函数来执行此操作:
inline fun <reified T : Any> classOfList(list: List<T>) = T::class
Run Code Online (Sandbox Code Playgroud)
此解决方案仅限于T
在编译时已知实际类型参数的情况,因为inline
函数在编译时进行转换,并且编译器将其reified
类型参数替换为每个调用站点的实际类型.
在JVM上,泛型类的类型参数在运行时被擦除,并且基本上没有办法从任意位置检索它们List<T>
(例如,传递到非内联函数的列表,因为List<T>
- T
在编译时对于每个调用都不知道并在运行时擦除)
如果您需要更多地控制函数内的reified类型参数,您可能会发现此Q&A很有用.
归档时间: |
|
查看次数: |
6562 次 |
最近记录: |