Kotlin中的inline


inline/noinline/crossinline/reified

内联,这个概念无需多说.

kotlin中使用高阶函数在运行时会有一些性能损失:每一个函数都是一个对象,并且都会捕获一个闭包(哪些在函数体内可以访问到的变量),对函数对象和类进行内存分配,和虚拟调用都会引入一些运行时间开销.

因此kotlin中经常用inline来优化lambda表达式,比如我们常用的let,apply方法:

public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}

不过内联可能会导致生成的字节码增加,尽量不要将过大的函数进行内联.

禁用内联/noinline

有时候内联方法中传入了lambda表达式作为参数,但是又不想这个参数lambda内联,可以使用noinline禁用内联:

inline fun <reified T : Task> Project.task(noinline configuration: T.() -> Unit) = tasks.registering(T::class, configuration)

对于那些并没有什么益处的内联,编译器会产生一个警告

非局部返回

kotlin中我们只能对具名或者匿名函数使用正常的return来退出,在lambda表达式中则必须使用一个标签来return.

有一种情况例外,就是lambda是内联的,这个时候可以正常return(因为lambda的return也内联了).

这么说可能不清楚,来个例子吧:

fun funWithoutInline(block:() -> Unit){
   block()
}

inline fun funInline(block: () -> Unit){
   block()
}

fun test():Boolean{
   // 只能使用这种方式,不能直接return
   funWithoutInline {
      return@funWithoutInline
   }
   funInline {
      return true
   }
   funInline {
      return@funInline
   }
   return false
}

Break 和continue 在内联的lambda表达式暂时不可用.

内联lambda嵌套问题

对于一般嵌套的lambda没什么影响,内联的lambda则需要使用crossinline进行修饰:

inline fun embedInlineFun(crossinline block:()->Unit){
     Runnable {
        // 如果不加crossinline会报错
        block()
     }.run()
}
fun embedFun(block:()->Unit){
   Runnable {
      block()
   }.run()
}

具体化的类型参数

其实就是inline + reified + 泛型,最典型的例子就是下面这个:

inline fun <reified T: Activity> Context.startActivity(){
    startActivity(Intent(this,T::class.java))
}

这个修饰符的作用就是在方法内部可以使用具体化的类型参数.

reified 修饰符必须与 inline搭配使用

内联属性

不多说,看代码:

val foo: Foo
    inline get() = Foo()

var bar: Bar
    get() = ……
    inline set(v) { …… }

inline var bar: Bar
    get() = ……
    set(v) { …… }

文章作者: 姜康
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 姜康 !
评论
 上一篇
Kotlin中的泛型 Kotlin中的泛型
概念如果A,B表示类型,f(*)表示类型转换, <= 表示继承关系(如果 A <= B,则表示A是B的子类) 里氏替换原则(LSP) 子类对象可以在程序中替换基类对象,”SOLID”原则中的L就是这个. 协变 如果f(*)是
2020-10-14
下一篇 
Kotlin中的infix Kotlin中的infix
infix即 “中缀表示法”,比如 1 + 2表示操作符以中缀的形式处于操作数的中间.(对应的也有前缀表达式,后缀表达式) 在kotlin中有这样的几种调用: val map = mapOf<String,Int>(
2020-10-14
  目录