如何检查 Kotlin 中的泛型类型?
How to check generic type in Kotlin?
我有 class
class Generic<T : SuperType>()
此代码不正确
fun typeCheck(s: SuperType): Unit {
when(s){
is T -> //do some thin
}
}
但将 s
转换为类型 T
s as T
显示警告 - 不安全转换。
如何检查 s
是 T
类型?
泛型在运行时不会在 JVM 上具体化,因此在 Kotlin 中无法做到这一点。警告是正确的,因为编译器不可能生成任何在转换完成时会失败的指令,因此未检查转换,这意味着程序可能会或可能不会在以后的某个时候中断。
内联函数中的一个可能有用的相关功能是 reified type parameters。 类 虽然无法具体化类型参数,因此如果您对用例进行更多详细说明,我可以尝试帮助您实现您似乎需要的东西。
如果您需要检查某些东西是否属于通用类型 T
,您需要有一个 Class<T>
的实例来进行检查。这是 Java 中的常见技术,但在 Kotlin 中,我们可以使用内联工厂方法来获取 class 对象。
class Generic<T : Any>(val klass: Class<T>) {
companion object {
inline operator fun <reified T : Any>invoke() = Generic(T::class.java)
}
fun checkType(t: Any) {
when {
klass.isAssignableFrom(t.javaClass) -> println("Correct type")
else -> println("Wrong type")
}
}
}
fun main(vararg args: String) {
Generic<String>().checkType("foo")
Generic<String>().checkType(1)
}
我知道我有点晚了,但我只想回顾一下 Alexander Udalov 提供的答案。
事实上,在 Kotlin 中确定泛型参数的类型是不可能的,除非您使用内联函数并将泛型类型声明为 reified
。
不确定我是否能够完整准确地回答这个问题,但我觉得我的贡献对于那些试图这样做的人来说可能仍然有价值。假设您有一些数据 类,并且您想检查您正在处理的是哪种类型。
您可以使用这样的函数:
inline fun <reified T> checkType() = when (T::class) {
TypeA::class -> println("TypeA")
else -> println("Type not recognized")
}
但是,调用它的函数也必须是内联的,因此您可能需要编写类似
的内容
inline fun <reified T> someOtherFunction(data: T) {
checkType<T>
}
但是,如果您不允许使用内联函数(比如说在接口中!),您可以 'cheat' 系统,例如
class AmazingTypes {
inline fun <reified T> checkType(genericParameter: T) = when (T::class) {
TypeA::class -> println("TypeA")
else -> println("Type not recognized")
}
}
fun myAwesomeMethod(someParameter: Any) {
val amazingClass = AmazingClass()
amazingClass.checkType(someParameter)
}
这也是例子。
inline fun <reified T: ApiResponse> parseJson(body: String): T {
// handle OkResponse only
val klass = T::class.java
if (klass.isAssignableFrom(OkResponse::class.java)) {
return T::class.java.newInstance()
}
// handle others
return gson.from(body, T::class.java)
}
我有 class
class Generic<T : SuperType>()
此代码不正确
fun typeCheck(s: SuperType): Unit {
when(s){
is T -> //do some thin
}
}
但将 s
转换为类型 T
s as T
显示警告 - 不安全转换。
如何检查 s
是 T
类型?
泛型在运行时不会在 JVM 上具体化,因此在 Kotlin 中无法做到这一点。警告是正确的,因为编译器不可能生成任何在转换完成时会失败的指令,因此未检查转换,这意味着程序可能会或可能不会在以后的某个时候中断。
内联函数中的一个可能有用的相关功能是 reified type parameters。 类 虽然无法具体化类型参数,因此如果您对用例进行更多详细说明,我可以尝试帮助您实现您似乎需要的东西。
如果您需要检查某些东西是否属于通用类型 T
,您需要有一个 Class<T>
的实例来进行检查。这是 Java 中的常见技术,但在 Kotlin 中,我们可以使用内联工厂方法来获取 class 对象。
class Generic<T : Any>(val klass: Class<T>) {
companion object {
inline operator fun <reified T : Any>invoke() = Generic(T::class.java)
}
fun checkType(t: Any) {
when {
klass.isAssignableFrom(t.javaClass) -> println("Correct type")
else -> println("Wrong type")
}
}
}
fun main(vararg args: String) {
Generic<String>().checkType("foo")
Generic<String>().checkType(1)
}
我知道我有点晚了,但我只想回顾一下 Alexander Udalov 提供的答案。
事实上,在 Kotlin 中确定泛型参数的类型是不可能的,除非您使用内联函数并将泛型类型声明为 reified
。
不确定我是否能够完整准确地回答这个问题,但我觉得我的贡献对于那些试图这样做的人来说可能仍然有价值。假设您有一些数据 类,并且您想检查您正在处理的是哪种类型。
您可以使用这样的函数:
inline fun <reified T> checkType() = when (T::class) {
TypeA::class -> println("TypeA")
else -> println("Type not recognized")
}
但是,调用它的函数也必须是内联的,因此您可能需要编写类似
的内容inline fun <reified T> someOtherFunction(data: T) {
checkType<T>
}
但是,如果您不允许使用内联函数(比如说在接口中!),您可以 'cheat' 系统,例如
class AmazingTypes {
inline fun <reified T> checkType(genericParameter: T) = when (T::class) {
TypeA::class -> println("TypeA")
else -> println("Type not recognized")
}
}
fun myAwesomeMethod(someParameter: Any) {
val amazingClass = AmazingClass()
amazingClass.checkType(someParameter)
}
这也是例子。
inline fun <reified T: ApiResponse> parseJson(body: String): T {
// handle OkResponse only
val klass = T::class.java
if (klass.isAssignableFrom(OkResponse::class.java)) {
return T::class.java.newInstance()
}
// handle others
return gson.from(body, T::class.java)
}