如何检查泛型是否是使用内联函数的数组?
我尝试了以下代码:
class Mediator {
inline fun <reified C> mediate(string: String): Container<C> {
if (C::class == Int::class) {
//It works
}
else if (C::class == Array::class) {
//It doesn't work!
}
throw IllegalStateException("Yopta")
}
}
但是它不起作用。也许因为它可以是Array<Whatever>
?
我该怎么做?
与集合相反,例如List<String>
和List<Int>
在内部由同一个类List
表示,在数组中类型参数是类型本身的一部分。这意味着Array<String>
和Array<Int>
在内部被表示为不同的类型,据我所知,它们没有一个共同的超类型。
我不知道一个纯Kotlin解决方案来检查一个类是否是一个数组。在我看来,这似乎是反射API设计中的一个疏忽。如果您不介意使用Java反射,您可以这样做:
else if (C::class.java.isArray) {
这里有一个有趣的事实。在Kotlin类型系统中,我们可以将Array<out Any?>
视为所有数组的超类型。例如,可以在不使用显式强制转换操作符的情况下向上强制转换:
val intArray = arrayOf(1, 2, 3)
val arr: Array<out Any?> = intArray
然而,对于反射API,这两种类型是完全不同的:
// false
println(Array<Int>::class.isSubclassOf(Array<out Any?>::class))
我认为这是由于数组在Java中是如何实现的。我甚至不确定是否在技术上可以在上面的代码中返回true
。但是,它在编译时提供的结果与类型系统不同,而且它甚至没有产生警告。
解决问题的实际答案。
既然broot添加了一个实际的答案,我就把这个留在这里,作为我们如何看出他基本上是正确的注释。
如果我们像这样调用:
Mediator().mediate<Array<Int>>("")
像这样在函数中添加一个简单的检查会让人有点困惑,为什么它们不相等。
println(C::class) //class Kotlin.Array
println(Array:class) //class Kotlin.Array
但是对底层java类做同样的操作会显示它们实际上不是同一个对象。
println(C::class.java) //class [Ljava.lang.Integer
println(Array:class.java) //class [Ljava.lang.Object
因此将语句改为:
if(C::class.java == Array<Int>::class.java)
将使示例工作…仅适用于Int
。所有其他的"无限"可能性将不得不手动添加。如果你只想检查Array<X>
,这不是问题,但绝对不是通用的。