07 inline、noinline & crossinline

175 阅读2分钟

inline

Kotlin的inline是一种修饰符,它可以让编译器在调用一个函数时,把函数的代码直接插入到调用处,而不是生成一个函数对象和一个函数调用。这样可以避免一些运行时的开销,如内存分配和虚拟调用。

Kotlin的inline可以内联内部的函数,也就是说,如果一个inline函数有一个或多个函数类型的参数,那么这些参数对应的函数也可以被内联到调用处。例如:

inline fun foo(inlined: () -> Unit) {
    println("foo")
    inlined()
}

fun main() {
    foo { println("inlined") }
}

这段代码在编译后相当于:

fun main() {
    println("foo")
    println("inlined")
}

这样可以减少创建函数对象和调用函数的开销。

但是,并不是所有的函数类型的参数都可以被内联。有些情况下,我们可能不想或不能内联某些函数,比如:

  • 我们想把函数类型的参数存储在一个变量或字段中,或者把它传递给另一个函数。
  • 我们想在函数类型的参数中使用非局部返回(non-local return),也就是说,我们想让它能够退出外部函数。

为了处理这些情况,Kotlin提供了两个关键字:noinline和crossinline。

noinline

  • noinline可以让我们标记某些函数类型的参数,表示它们不应该被内联。这样,我们就可以自由地操作这些参数,而不受内联的限制。例如:
inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) {
    // ...
}

crossinline

  • crossinline可以让我们标记某些函数类型的参数,表示它们应该被内联,但是不能使用非局部返回。这样,我们就可以保证内联的正确性,而不影响外部函数的控制流。例如:
inline fun foo(crossinline inlined: () -> Unit) {
    bar { inlined() }
}

fun bar(block: () -> Unit) {
    // ...
}

总结

image.png