inline、noinline、crossline区别?
inline:编译时把inline函数的代码拷贝到调用处
noinline:修饰inline标记的函数的形参,不希望内联lambda
crossline:inline函数中的lambda表达式不允许返回到外部函数,只能返回到lambda表达式
inline作用
Java中没有函数的概念,Kotlin中的lambda表达式在Java中对应的是一个FunctionN的单个方法的接口类,创建一个lambda表达式相当于创建一个类。
inline可以修饰函数,inline修饰的函数的形参中有lambda表达式,编译时不会创建对应的FunctionN类,而是直接把lambda表达式代码拷贝到调用处,这样
- 在循环等高频使用一个函数的场景下,内联lambda表达式避免了频繁创建对象,不仅节约了内存,也避免了频繁的垃圾回收,减少系统卡顿
- 减少了函数调用层级,函数调用栈少了一层,减少了性能损耗
inline会造成什么问题?
- 调用处的代码变多,所以不能内联代码量过大的函数,只适用于内联代码量小的函数
- 我们可以在inline函数形参的 lambda 表达式 中调用return直接返回外部函数,可能会导致inline函数之后的代码无法执行;需要使用return@label的语法,返回到lambda开始执行的位置
- 内联后的lambda表达式已经不是对象了,所以无法作为参数传递、存储在字段中、作为返回值return,需要加noinline解决
noinline作用
修饰inline函数的形参中的lambda表达式,表示禁止该lambda表达式内联
noinline禁止lambda表达式内联的意义是什么?
内联后的lambda表达式已经不是对象了,所以无法作为对象使用,也就是无法对其进行参数传递、存储在字段中、作为返回值return,需要加noinline解决
crossinline作用
既想让内联函数形参中的 lambda 也被 inline,但是又不想让 lambda 对调用方的控制流程产生影响(lambda中return会影响),就用crossline
crossinline依然是内联的
直接在lambda表达式中返回外部函数的情况称为非局部返回。
crossinline修饰的lambda禁止了非局部返回
crossinline为什么要禁止非局部返回?不禁止会有什么问题?
内联函数形参中的lambda表达式可能会在另外一个调用栈中执行,例如:
1 | inline fun f(crossinline body: () -> Unit) { |
正常情况下内联的lambda允许非局部返回,返回的是内联函数调用处的函数,但是不在一个调用栈中,非局部返回就无法做到这样的返回,所以必须禁止,用crossinline来禁止非局部返回,但仍然保持内联的特性,把lambda表达式的代码展开铺平。
内联类
- 内联函数,可以消除函数调用的开销。
- 内联类,则是可以消除创建对象的开销。
用途:
- 严格的类型别名
- 任何你想得到的包装类(wrapper)