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

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("不支持的类型")
        }
    }
  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值