内联函数

首先,一般情况下。lambda 表达式会被正常地编译成匿名类。这表示每调用一次lambda 表达式,一个额外的类就会被创建。并且如果 lambda 捕捉了某个变量,那么每次调用的时候都会创建一个新的对象 这会带来运行时的额外开销,导致使lambda 比使用一个直接执行相同代码的函数效率更低。

而内联函数可以解决这个效率低下的问题,也就是使用inline关键字,他在编译后,不会是一个调用函数的代码,而是直接把函数体复制并替换到当前位置,然后直接执行。

使用条件

一般情况下都可以使用,但是最推荐,当你使用lambda函数时,因为这样子可以最大的提高效率。
而如果你使用的lambda函数已经被定义到某个具体的类中时,或者被作为一个参数接收起来。
总而言之就是必须要现场写的lambda函数。他的使用才有意义。不然他将不会被内联进来,只会编译为调用函数的过程。

JVM自动内联

对于普通的函数调用,JVM己经提供了强大的内联支持。它会分析代码的执行,并在任何通过内联能够带来好处的时候将函数调用内联。这是在将宇节码转换成机器代码时自动完成的。在字节码中,每一个函数的实现只会出现一次,并不需要跟Kotlin 的内联函数一样,每个调用的地方都拷贝一次。再说,如果函数被直接调用,调用只会更加清晰。

但是如果内联的代码太大也会很难看。

高阶函数控制

如果我们使用lambda如forEach的函数时,就会很快遇到关于return的问题。因为他的return会直接从最外层的函数返回。

  1. 如果你在lambda函数中使用return,那么他默认会从调用lambda函数的函数中返回。并不只是从lambda函数返回。这个被称为非局部返回。

    需要注意的是,只有在以 lambda 作为参数的函数是内联函数的时候才能从外层的函数返回。

  2. 如果我们要从lambda函数中局部返回,可以使用标签,或者从函数名返回。(类似于continue的实现)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //1 函数名
    "123141".forEach {
    if (it == '1') {
    return@forEach
    }
    }
    //2 标签
    "123141".forEach lable@{
    if (it == '1') {
    return@lable
    }
    }

    一个 lambda 表达式的标签数量不能多于一个。也就是使用了标签,函数名就无法使用了。

  3. 匿名函数默认从lambda函数返回,也就是和普通的非内联lambda一致。