在Java中,泛型是只存在于编译阶段的,这就要我们了解Java中泛型的擦除机制,就是说虽然我们在写代码的时候写了泛型,但是程序真正运行的时候,并不知道我们的具体类型是什么,泛型的约束只在编译时期存在。比如我们写了List< String>集合,在编译时期,我们是无法向该list中添加非String的元素的,但是在运行时期,我们并不能知道该list里放的是哪种元素。也就是说我们写了Lsit< T>,我们并不能在运行的时候遍历该list,然后打印出T.class。因为T的实际类型在运行是已经被擦除了,但是在Kotlin中,我们就有办法实现T::Class.java的相关功能,该原理就叫做泛型的实话。
我们还要知道的是:所有的基于jvm的语言,它们的泛型都是通过类型擦除机制来实现的,但是我们的Kotlin为什么能实现不一样的东西呢,还记得我们在之前学过Kotlin中的高阶函数的内联功能吗?Kotlin-高阶函数详解,inline, noinline, crossinline关键字解析(第一行代码Kotlin学习笔记7),内联函数中的代码会在编译的时候被替换到调用它的地方,这样的话,如果我们在内联函数中使用了泛型,那么编译过后,使用的其实就是该泛型对应的真实类型了。具体使用也很简单,我们只需要在泛型前用reified关键字修饰就可以了:
inline fun <reified T> getType() {}
然后我们就可以实现这样的功能:
inline fun <reified T> getType() = T::class.java
fun main() {
var type = getType<String>()
println("tyep is : $type")
}
//tyep is : class java.lang.String
由此可见,我们可以使用泛型,获取到它所对应的真实类型,这样的功能在Java中我们是做不到的,但是,这个功能有什么卵用呢?
如果我们要跳转到某个activity,如OpentActivity,我们会这么写:
val intent = Intent(this,OpentActivity::class.java)
startActivity(intent)
其实以前我们使用Java编程的时候,也是同样的思路,但是,有了泛型的实化,我们就有了更加优雅的处理方式:
inline fun <reified T>startActivity(context : Context){
val intent = Intent(context,T::class.java)
context.startActivity(intent)
}
我们首先定义了自己的startActivity()方法,然后,当我们需要启动某个activity时,比如我们依然在某个activity中启动OpentActivity,这样写就可以了
startActivity<OpentActivity>(this)
如果我们想要在intent中添加我们想要携带的参数怎么办呢?这里就可以使用我们之前学到的高阶函数了,我们可以写一个重载函数:
inline fun <reified T>startActivity(context : Context,block: (Intent.() -> Unit)){
val intent = Intent(context,T::class.java)
intent.block()
context.startActivity(intent)
}
然后可以这样使用:
startActivity<OpentActivity>(this){
putExtra("key","value")
}
这样使用是不是就比之前方便多了,如果我们有自己的BaseActivity,我们完全可以将此方法定义在BaseActivity,大概就是这个样子:
open class BaseActivity : AppCompatActivity() {
inline fun <reified T>startActivity() {
val intent = Intent(this,T::class.java)
startActivity(intent)
}
inline fun <reified T>startActivity(block:Intent.() -> Unit) {
val intent = Intent(this,T::class.java)
intent.block()
startActivity(intent)
}
}
然后我们的业务activity继承BaseActivity:
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
startActivity<OpentActivity>(){
putExtra("key","value")
}
}
}
}