一分钟学习kotlin -- 内联函数

207 阅读2分钟

定义: 内联函数就是普通函数之前增加了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对象。