inline & noline & crossinline
class TestInline {
@JvmField
val TAG = "Test"
fun main() {
Log.i(TAG, "main")
test1 {
Log.i(TAG, "test0")
}
}
private fun test1(test0: () -> Unit) {
Log.i(TAG, "before test0")
test0()
Log.i(TAG, "after test0")
Log.i(TAG, "before test2")
test2()
Log.i(TAG, "after test2")
}
private fun test2() {
Log.i(TAG, "test2")
}
}
根据上面的类作为一个 demo 来进行分析一下:
Decompile TestInline.kt 文件的 Bytecode 得到如下 Java 文件:
public final class TestInline {
@JvmField
@NotNull
public final String TAG = "Test";
public final void main() {
Log.i(this.TAG, "main");
this.test1((Function0)(new Function0() {
// $FF: synthetic method
// $FF: bridge method
public Object invoke() {
this.invoke();
return Unit.INSTANCE;
}
public final void invoke() {
Log.i(TestInline.this.TAG, "test0");
}
}));
}
private final void test1(Function0 test0) {
Log.i(this.TAG, "before test0");
test0.invoke();
Log.i(this.TAG, "after test0");
Log.i(this.TAG, "before test2");
this.test2();
Log.i(this.TAG, "after test2");
}
private final void test2() {
Log.i(this.TAG, "test2");
}
}
会发现
test0: () -> Unit
这个 lambda 表达式被转成了 Function0 这个接口。
Kotlin-stdlib-1.3.11-source.jar
kotlin.jvm.functions.Functions.kt
这个文件内部定义了 23 个 「Function」接口。
test1(test0: () -> Unit) // 这个函数的调用变成了对匿名内部类的函数回调
相当与lambda函数的调用会产生一些额外开销。
上面的 demo 还只是创建一个匿名内部类来使用,假如是多个呢?
fun main() {
Log.i(TAG, "main")
intArrayOf(1, 2, 3, 4, 5).forEach {
test1 {
Log.i(TAG, "test0 -- $it")