Kotlin内联函数
2019-08-10 本文已影响15人
程序员丶星霖
调用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。
学海无涯苦作舟
