前语
在前两篇文章中咱们介绍到Kotlin中的函数、高阶函数和Lambda表达式。这篇文章咱们来讲解Kotlin源码中常见的三个关键字inline、noinline、crossinline的运用,当然这是在把握了前两篇文章的基础上来打开介绍的。如果对Kotlin中的函数、高阶函数和Lambda表达式不熟悉的读者,能够看下这两篇文章。下面咱们开始本篇文章的学习。
1.部分回来
在介绍inline关键字之前,咱们有必要先来介绍下Kotlin中部分回来的概念。那么什么是部分回来呢? 在Kotlin中非内联的Lambda表达式是不支撑运用裸return的,在非内联的Lambda表达式内部咱们只能运用标签约束的return来进行部分回来。如果咱们强行在一个Lambda表达式中运用裸return,编译器会报语法错误。如下示例代码,咱们在main函数中调用高阶函数normal的时分运用裸return:


fun main() {
normal test@{
println("called normal")
return@test
}
}
fun normal(block:() -> Unit) {
block()
}
能够看到咱们只需求在lambda表达式的花括号外运用@符号,并在@符号前加上咱们自界说的标签名,这样咱们就能够给一个Lambda表达式显现的声明一个标签名。如上示例代码,咱们给normal函数声明晰一个test的标签名,这样咱们在Lambda表达式中就能够运用咱们自界说的标签来完结当时高阶函数的部分回来。 为了验证带有@标签约束的return仅仅部分回来,咱们在上面main函数的首行和尾行各打印一行代码,如下:
fun main() {
println("main called start")
normal {
println("normal called start")
return@normal
println("normal called end")
}
println("main called end")
}
fun normal(block:() -> Unit) {
block()
}
// 输出
main called start
normal called start
main called end
从上述代码的打印结果咱们能够看到retrun@normal仅仅仅仅对直接包裹它的外层函数normal进行了回来,而并没有对最外层的main函数进行回来。
2.inline
在Kotlin中运用关键字inline润饰一个函数的时分,咱们就称这个函数是内联函数。内联函数不只能够内联自己函数体内部的代码,还能够内联函数体内部函数体的代码(Lambda表达式中的代码)。下面咱们先来看一下示例代码:
fun main() {
normal { println("normal called") }
}
fun normal(block:() -> Unit) {
println("normal started")
block()
println("normal end")
}
咱们知道,Kotlin代码终究仍是要编译成Java字节码的。在Android Studio中选择Tools -> Kotlin -> Show Kotlin Bytecode,在右边弹出的方框中,咱们点击Decompile按钮。


fun main() {
println("main started")
normal {
println("normal called")
return
}
println("main end")
}
inline fun normal(block:() -> Unit) {
block()
}
// 输出
main started
normal called
能够看到当咱们运用inline关键字润饰normal函数的时分,在main函数中咱们能够直接在normal函数中运用裸return来完结最外层函数main的回来。 到这儿咱们就能够总结一下inline关键字的长处和缺点了:
- 对于普通的函数,运用内联函数是完全没有必要的,仅仅减少了一次办法栈的调用,这种优化能够忽略
- 对于带有函数类型参数的高阶函数,咱们运用inline关键字润饰的内联函数,来节省Lambda表达式在调用的当地创立匿名类带来的内存开销
- 由于内联函数,不只能够内联自己内部的代码,还能够内联内部的内部中的代码(Lambda表达式中的代码)。在调用的当地仅仅仅仅代码的替换,咱们能够在Lambda表达式中,直接运用裸return来完结最外层函数的回来。这种回来(位于 lambda 表达式中,但退出包含它的函数)咱们称之为非部分回来。
- 如果需求内联的函数代码逻辑过于杂乱,调用该函数又比较频频,则会导致调用该内联函数的当地出现代码臃肿的状况。
3.noinline
在Kotlin中noinline关键字总是和inline关键字成对的出现。翻译成中文的意思便是禁用内联,咱们先来看一下,如下的代码场景:


4.crossinline
在一些实践开发的场景中,内联函数内部可能会将咱们函数类型实例的调用放在一个外部上下文作用域的Lambda表达式中。关于带有上下文作用域的Lambda表达式,咱们已经在上一篇高阶函数和Lambda表达式中具体介绍,这儿就不再介绍了。例如咱们需求将UI代码放在主线程中去履行,咱们通常会这么写:


但同时咱们也向Kotlin编译器保证了,不会在调用该内联函数的时分,在Lmabda表达式中运用裸return。如上面代码示例,咱们在内联函数runInMainThead办法中已经没有办法运用裸return了,只能运用标签约束的return。
总结
关于inline、noinline、crossinline关键字的运用到这儿就介绍完了。娴熟的把握了这一节的内容,对于咱们阅览源码和实践开发会有很大的帮助。下篇文章笔者计划结合一下自己在开发中对扩展函数和高阶函数的运用打开介绍,咱们下期再见!


