内联函数基本概念与使用
我们在使用Lambda表达式调用高阶函数时,实际上Lambda表达式在底层会被转换成匿名类的实现方式,所以每当我们调用一次就会创建一个匿名类,这回造成额外的内存和性能开销,然而内联函数就是解决这一问题的方法,它可以将这种运行时开销完全消除。
内联函数的基本使用方法:在定义高阶函数时给它加上inline关键字声明
例如
inline fun num1AndNum2(num1:Int,num2:Int,calculate:(n1:Int,n2:Int)->Int):Int{
return calculate(num1,num2)
}
工作原理:Kotlin编译器会将内联函数中的代码在编译的时候自动替换到调用它的地方
下面我举例说明
-
首先Lambda表达式中的代码会被替换到内联函数当中函数类型参数调用的地方
-
然后内联函数中所有的代码会被替换到内联函数调用的地方
-
最终的代码就是这样了
noinline(不内联)
内联的函数类型参数在编译的时候代码会进行替换,所以它没有真正意义上的参数属性,只能传递给另一个内联函数;而非内联函数有真正的参数属性,它可以传递给任何函数。由于内联的函数存在这种局限性,Kotlin就提出了noinline来处理这种尴尬的情况。
如果我们内联函数中有多个函数类型参数,但是我们只想内联其中某些,这是就使用oninline来达到我们的目的
inline fun test(do1:(Int)->Unit,noinline do2:()->Unit){
}
在这个内联函数中我们给do2参数生命了noinline关键字,所以只有do1会被内联
注意:内联函数可以使用return关键字进行函数返回,非内联函数()只能使用return@函数名的方式进行局部返回
crossinline
保证内联函数的Lambda表达式中一定不会使用return
如果我们在声明为内联函数的高阶函数中创建了另外的Lambda或者匿名类的实现,并且在这些实现中调用了函数类型参数,就会提示错误,原因如下
- Lambda表达式在编译的时候会被转换成匿名类的实现方式,这里就是将函数类型参数传入匿名类调用
- 内联函数是允许使用return的
- 但是由于是在匿名类中调用的函数类型参数(类似与非内联函数,不能使用return),所以不能使用return进行外层调用返回