定义: 内联函数就是普通函数之前增加了inline关键字修饰。
内联函数的特点:在编译时期会把内联函数复制到调用的地方。
内联函数通常会用在高阶函数中,提升高级函数性能。在高阶函数调用过程中,会给内部函数生成一个闭包(函数对象),虚拟机会对这个闭包对象(类和函数对象)进行内存分配,虚拟机在调用时也会引入一些额外的开销,使用内联函数就没有创建对象以及管理对象引用等开销。
fun main() {
hello {
println("write kotlin...")
}
}
inline fun hello(block: () -> Unit) {
println("before block")
block()
}
内联函数的限制:
inline会增加代码量,所以要避免大型内联函数。
内联函数不能保存传入函数参数引用,也不能把传入的函数参数参数传给林外一个函数。
noinline关键字可以禁用内联
如果需要保存函数类型参数,需要在函数参数前面使用noinline 关键字,禁止内联。
如果需要把函数参数传给另外的函数,使用noinline也不会提高性能,这时就不建议使用内联函数。
lambda表达式无法包含它自己的返回,不能直接使用return。如果lambda是内联的,那么它是允许的,这个被称为非局部返回。
具体化类型参数
普通使用参数类型, 这种方式我们需要指定类class和具体的实例参数T
fun <T> TreeNode.findParentOfType(clazz: Class<T>): T? {
var p = parent
while (p != null && !clazz.isInstance(p)) {
p = p.parent
}
@Suppress("UNCHECKED_CAST")
return p as T?
}
//调用
treeNode.findParentOfType(MyTreeNode::class.java)
支持具体化类型的内联函数 ,只需要指定reified 类型就可以了
inline fun <reified T> TreeNode.findParentOfType(): T? {
var p = parent
while (p != null && p !is T) {
p = p.parent
}
return p as T?
}
//调用
myTree.findParentOfType<MyTreeNodeType>()。
在内联函数中使用reified 指定类型,内联函数会拷贝一份函数到调用的地方,在编译的时候,就已经知道类型信息,在新生成字节码的时候就能指定类型信息,并且使用类型信息,没有用到java中的类型清除,所以整个过程不需要再指定class对象。
前面文章中有一个使用到的例子就是启动activity的时候
inline fun <reified T : Activity> Activity.startActivity(context: Context) {
startActivity(Intent(context, T::class.java))
}
//使用
startActivity<NewActivity>(context)
使用reified简化了参数,可以直接传递对象类型,运行的时候就可以取得class对象。