Kotlin的泛型与Java不同的是,Kotlin可以做到判断泛型类型的功能,那就非常的有用了。
假如需要写一个打印泛型参数具体类型的方法,我相信大部分觉得第一反应是这样写:
写完才发现它居然报错: Cannot use 'T' as reified type parameter. Use a class instead 意思大概就是泛型推断不了具体类型吧。
Kotlin提供了reified 关键字,它就是提供泛型类型推断的功能的。它一般都要和inline结合一齐使用。
上面代码修改一下可以变成这样实现:
inline fun <reified T> getType(value: T) {
println("$value 的类型是 ${T::class.java}")
}
在main方法中调用该函数看看结果:
fun main(args: Array<String>) {
getType("hello")
getType(132456)
getType(true)
}
程序运行结果
Kotlin的泛型类型推断功能还有一种最有用的地方,就是根据不同泛型类型调用不同的方法这种场景。
如Android的 Bundle 或 SharePreference都提供了 getString,getBoolean,getInt .... 这些获取不同类型的值的方法,我们这样就可以封装为一个方法了,如封装bundle为例:
//bundle 存值
fun <T> putBundleValue(key: String, value: T) {
when (value) {
is Int -> bundle.putInt(key, value)
is Long -> bundle.putLong(key, value)
is String -> bundle.putString(key, value)
is Boolean -> bundle.putBoolean(key, value)
else -> throw Exception("不支持的类型")
}
}
//bundle 取值
inline fun <reified T> getBundleValue(key: String): T {
return when (T::class.java) {
java.lang.Integer::class.java -> bundle.getInt(key) as T
java.lang.Long::class.java -> bundle.getLong(key) as T
java.lang.String::class.java -> bundle.getString(key) as T
java.lang.Boolean::class.java -> bundle.getBoolean(key) as T
// 注意不能写成以下形式,否则匹配不到类型,因为 reified 会推断为Java.lang包下的基本类型而不是kotlin包下的类型
// Int::class.java -> bundle.getInt(key) as T
// Long::class.java -> bundle.getLong(key) as T
// String::class.java -> bundle.getString(key) as T
// Boolean::class.java -> bundle.getBoolean(key) as T
else -> throw Exception("不支持的类型")
}
}
这样只用一个函数就能调用存取数据方便多了。
putValue("string", "hello")
putValue("bool", true)
val stringValue=getValue<String>("string")
val booleanValue:Boolean = getValue("bool") //声明类型后泛型能自动推导
补充一下: 如果限定泛型T为基本类型,其实也能这样投机取巧来实现
//bundle 取值
inline fun <reified T> getBundleValue(key: String): T {
return when {
0 is T -> bundle.getInt(key) as T //判断T是否为Int
1L is T-> bundle.getLong(key) as T //判断T是否为Long
"h" is T -> bundle.getString(key) as T //判断T是否为String类型
true is T -> bundle.getBoolean(key) as T //判断T是否为Boolean类型
else -> throw Exception("不支持的类型")
}
}