原创

Kotlin内联函数

调用Lambda表达式或函数的过程是:

程序要将执行顺序转移到被调用表达式或函数所在的内存地址,当被调用表达式或函数执行完后,再返回到原函数执行的地方。

在这个转移的过程中,系统会处理如下事情:

  • 为被调用的表达式或函数创建一个对象;
  • 为被调用的表达式或函数所捕获的变量创建一个副本;
  • 在跳转到被调用的表达式或函数所在的地址之前,要先保护现场并记录执行地址;从被调用的表达式或函数地址返回时,要先恢复现场,并按原来保存的地址继续执行。

一、内联函数的使用

使用inline关键字修饰带函数形参的函数就是内联函数。

fun main(args: Array<String>) {
    var arr = arrayOf(20, 4, 40, 100, 30)
    var mappedResult1 = map(arr, { it + 3 })
    println(mappedResult1.contentToString())
}

//定义函数类型的形参,其中fn是(Int)->Int类型的形参
inline fun map(data: Array<Int>, fn: (Int) -> Int): Array<Int> {
    var result = Array<Int>(data.size, { 0 })
    //遍历data数组的每个元素,并用fn函数对data[i]进行计算
    for (i in data.indices) {
        result[i] = fn(data[i])
    }
    return result
}

输出结果:

[23, 7, 43, 103, 33]

内联函数的本质是将被调用的Lambda表达式或函数的代码复制、粘贴到原来的执行函数中。

内联函数并不总是带来好处的,内联函数是以目标代码的增加为代价来节省时间开销的。

  • 如果被调用的Lambda表达式或函数包含大量的执行代码,就不应该使用内联函数;
  • 如果被调用的Lambda表达式或函数只包含非常简单的执行代码,那么就应该使用内联函数。

二、部分禁止内联

noinline用于显式组织某一个或某多个形参内联化。

fun main(args: Array<String>) {
    test({ it * it }, { "我要学${it}" })
}

inline fun test(fn1: (Int) -> Int, noinline fn2: (String) -> String) {
    println(fn1(20))
    println(fn2("Kotlin"))
}

输出结果:

400
我要学Kotlin

三、非局部返回

在Lambda表达式中直接使用return不是用于返回该表达式,而是用于返回该表达式所在的函数。

在默认情况下,在Lambda表达式中并不允许直接使用return。

在内联的Lambda表达式中可以使用return,该return就像直接写在lambda表达式的调用函数中一样。内联的Lambda表达式中的return可用于返回它所在的函数,这种返回被称为非局部返回

fun main(args: Array<String>) {
    var arr = arrayOf(20, 4, 40, 100, 30)
    each(arr, {
        println(it)
        //如果each函数没有inline修饰,此处编译错误
        //如果each函数有inline修饰,此处的return将返回main函数
        return
    })
}

//定义函数类型的形参,其中fn是(Int)->Unit类型的形参
inline fun each(data: Array<Int>, fn: (Int) -> Unit) {
    for (el in data) {
        fn(el)
    }
}

输出结果:

20

在非内联的Lambda表达式中不能使用return。

学海无涯苦作舟

我的微信公众号.jpg

基本语法
  • 作者:HunterArley (联系作者)
  • 发表时间:2019-11-21 10:49
  • 版权声明:本网站部分内容转载于合作站点或其他站点,但都会注明作/译者和原出处。如有不妥之处,敬请指出。
  • 公众号转载:请在文末添加作者公众号二维码