kotlin 深入学习笔记(四)
Contents
本文主要介绍kotlin的inline
关键字。
inline
在kotlin中使用高阶方法确实很方便,但是这种便利是有代价的。我们知道 lambda 表达式其实就是一个 Function 对象。
例如:
fun nonInlined(block: () -> Unit) { |
对应Java代码为
public void nonInlined(Function block) { |
在kotlin中调用时
nonInlined { |
会被编译为下面的代码(简化)
nonInlined(new Function() { |
这里每次调用nonInlined()
都会创建一个Function对象。如果这里调用的是非常通用的高阶函数,那么每次调用都会带来额外的内存、运行开销。
inline
就是 kotlin 是用来优化这个问题的关键字。
inline fun inlined(block: () -> Unit) { |
调用和之前一样
inlined { |
对应编译后的代码
System.out.println("before"); |
使用inline可以增加运行效率,降低内存占用。相应的,带来的副作用就是代码膨胀。所以,inline 的最佳使用场景是一些短小的高阶函数,或者需要在循环中调用的函数。
在 kotlin std 库中定义的高阶函数基本上都是被inline 修饰的,我们自己在写库时也可以使用这个优化点。
但是,被inline的函数有一些副作用。
1、被inline的函数,无法在函数内部访问private变量、方法(除非用internal
和@PublishedApi
修饰)。
private val aPrivateMemberVariable = "I'm private" |
2、在被inline
修饰的Function闭包内运行的lambda 中,可以使用 return 退出 calling 函数。
这种特性也被称为non-local control flow
。
这样做其实是为了让我们可以在forEach
中的lambda有能力控制循环。
fun hasZeros(ints: List<Int>): Boolean { |
但是,截止到1.1.4,kotlin 还不支持在non-local control flow
中使用break
和continue
。😂
这个特性其实很容易产生bug,因为这样做的话,相当于剥夺了高阶函数对lambda运行的控制。比如在涉及资源处理时,乱用return很容易跳过了资源释放语句,而且不易调试。
而正常的lambda是没有能力return执行函数的,只能通过 return@label
的方式跳出 lambda自身。
inline fun higherOrderFunction(aLambda: () -> Unit) { |
除了inline
,kotlin中还有noinline
、crossinline
等关键字。
noinline
顾名思义,和inline
含义相反。用于标记某个lambda,表示这个lambda在inline
Function内不内联。
crossinline
用的比较少,主要用于在嵌套的Function内部使用lambda,被crossinline
标记的lambda不能在lambda内部使用return。
inline fun higherOrderFunction(crossinline aLambda: () -> Unit) { |
Author: deskid
Link: https://deskid.github.io/2017/09/07/kotlin-learn-notes-4/
License: 知识共享署名-非商业性使用 4.0 国际许可协议