Kotlin 之 inline & noline & crossinline

本文详细介绍了Kotlin的inline、noinline和crossinline关键字,通过Bytecode分析展示了它们如何影响lambda表达式。inline避免了多次调用lambda时的匿名内部类开销,但与return的使用有特殊要求。noinline则限制了lambda的inline处理,不允许直接使用return,而crossinline允许在保持inline效果的同时防止直接的return。此外,文章提及break和continue在内联lambda中的支持现状,并给出了在forEach中跳出循环的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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")
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值