inline
inline
修饰函数,表示內联函数,对函数进行优化,调用对函数在编译时变成代码内嵌对形式,相当于把函数体展开,平铺到调用处。这样的好处时减少了函数的调用栈,但是这种好处小到可以忽略不计,甚至如果函数体过大,并且调用函数有很多此,就会导致每个调用函数的地方都平铺函数体,造成字节码体积过大,形成负优化。
inline fun f1(){//这种优化并没有什么用,android studio都出现警告了
println("inline")
}
内联最适用于具有函数类型参数的函数,因为kotlin的函数类型在jvm编译时会是一个对象,使用inline修饰时可以减少对象的创建
inline fun i1(callback:()->Unit){
println("hello")
callback.invoke()
}
fun main() {
i1{
println("inline")
}
}
//相当于
fun main(){
println("hello")
println("inline")
}
在inline修饰的函数中,并且函数参数是函数类型,在调用函数时,可以在lambda中写return,表示的是返回此函数的外层函数。lambda表达式中不能使用return,除非这个了lambda是內联函数的参数
inline fun i1(callback:()->Unit){
println("hello")
callback.invoke()
}
fun main() {
i1{
println("inline")
return
}
}
//相当于
fun main() {
println("hello")
println("inline")
return
}
noinline
noinline
用来修饰函数类型参数,可以对一个或多个函数类型参数取消內联优化。因为函数类型实质上是一个对象,如果这个对象不需要被使用,使用inline没问题,一旦需要用到这个对象时,就不能使用inline了,inline的本质是将函数平铺到调用方,内部的函数类型的参数不再是对象了。
inline fun i2( pre:(String)->Int, after:(Int)->String){
pre("ll")
println("hello")
val a = after//对象赋值,用到对象,这时会报错,必须把这个参数用noline修饰
}
inline fun i2( pre:(String)->Int,noinline after:(Int)->String){
pre("ll")
println("hello")
val a = after
}
用来局部的关闭优化,因为这种优化会导致函数中的函数类型的参数无法被当做对象使用。
crossinline
crossinline
也是修饰函数类型参数,是加强inline內联优化,可以间接调用函数类型的参数。
內联函数不允许函数类型参数被间接调用
inline fun f1(block:()->Unit){
f2{
block.invoke()//在f2中调用函数类型,间接调用,是不被允许的,报错
}
}
fun f2(block: () -> Unit){
}
解决上面问题的办法是在函数类型的参数用crossinline进行修饰
inline fun f1(crossinline block:()->Unit){
f2{
block.invoke()
}
}
fun f2(block: () -> Unit){
}