什么是内联(inline)函数

首先 inline 借鉴至 c++, 主要作用是降低程序的运行时间。当内联函数收到编译器的指示时,编译器将使用函数的定义体替代函数调用语句,这种替换行为发生在编译阶段而非程序运行阶段。

在kotlin中,函数就是对象,当你调用某个函数的时候,就会创建相关的对象(内存开销的原因)

下面用两个实际例子说明两种区别

  • 非inline函数的调用过程Inline Functions - 图1

  • inline函数的调用过程 Inline Functions - 图2

Kolin中的 inline,noinline

在Kolin中如果声明fun为 inline,默认所有该函数用的lambda也是内联,如下:Inline Functions - 图3
当前可以通过 noinline 来改变这特性

  1. //lambda加上noinline强制不内联
  2. inline fun doSum(a: Int, b: Int,noinline cal : (Int,Int) -> Int) : Int{
  3. val sum = cal(a,b)
  4. print("sum $sum")
  5. return sum
  6. }

Kotlin中的 return,non-local return

return

在kotlin中,return 只能用在有名字的函数或匿名函数中,使得该函数执行完毕。 而针对lambda表达式,你不能直接使用return

报错示例:Inline Functions - 图4
但是可以通过 lambda + label 结束此lambda执行(lambda的默认是label名为函数名字)

    {      
        //返回默认的label
        doWork { return@doWork}
        //返回自定义的label
        doWork finish@{ return@finish}
    }

    fun doWork(work: () -> Unit){
    }

那么如何直接在lambda中使用return ? 内联(inline函数)

    doInlineWork{
        //由于doInlineWork是inline标记的函数,因此可以直接使用return
        return
    }
}

inline fun doInlineWork(work: () -> Unit){
}


之所有加上 inline 后就能直接使用return ,是因为内联函数在编译的时候,将相关的代码贴入你调用的地方。 lambda表达式也只是一段代码而已,这时候你在lambda中的return,相当于在你调用的方法内return

non-local return

首先知晓一个情况:一个函数中,如果存在一个lambda表达式,在该lambda中不支持直接进行return退出该函数,但是匿名或者具名函数则可以,如下所示

fun outterFun() {
    innerFun {
        //return  //错误,不支持直接return
        //只支持通过标签,返回innerFun
        return@innerFun
    }

    //如果是匿名或者具名函数,则支持
    var f = fun(){
        return
    }
}

fun innerFun(a: () -> Unit) {}

除非,innerFun是inline函数:

fun outterFun() {
    innerFun {
        return  //支持直接返回outterFun
    }
}
inline fun innerFun(a: () -> Unit) {}

上述这种直接在lambda中返回外部函数的称为non-local return (非局部返回)

Kotlin中的 crossline

crossline 是针对 non-local return 使用,让被标记的lambda表达式不允许 non-local return(非局部返回), 因为默认内联函数的lambda表达式参数是允许非局部返回的(及返回外部函数)
如下:

fun outterFun() {
    innerFun {
        return  //支持直接返回outterFun
    }
}
inline fun innerFun(a: () -> Unit) {}

当通过将innerFun的lambda参数标记为crossinline后,return操作将不被允许

fun outterFun() {
    innerFun {
        return  //因为lambda参数加上了 crossinlen因此 这里就不合法
    }
}
inline fun innerFun(crossinline a: () -> Unit) {}