检查generic是否是带有内联函数的数组



如何检查泛型是否是使用内联函数的数组?

我尝试了以下代码:

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>,这不是问题,但绝对不是通用的。

最新更新