使用Kotlin推断泛型的具体类型,以及 reified 关键字的使用

tech2026-04-10  2

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("不支持的类型") } }
最新回复(0)