使用高阶函数带来了相应的运行时麻烦:每个函数都是一个对象,它捕获闭包,即这些变量可以在函数体内被访问。内存的分配,虚拟调用的运行都会带来开销。但在大多数这种开销是可以通过内联文本函数避免。
让Lambda表达式内联进函数
使用高阶含少,在运行时会带来一些不利。每个函数都是一个对象,而且它还要捕获一个闭包,也就是在函数体内部访问的那些外层变量。内存占用(函数对象和类都会占用内存)以及虚方法调用都会带来运行时的消耗。
在这种情况下,通过将Lambda表达式内联在使用处,可以消除这些运行时消耗。要想让函数支持关联,==需要在定义函数时使用inline关键字==。
// 被内联的函数体不能太大
inline fun processProduct(area:(name:String)->String):String
{
return area("iPhone")
}
fun main(args: Array<String>)
{
println(processProduct({name->"${name} 美国"}))
}
输出:
iPhone 美国
内联部分Lambda表达式
inline fun process1(area1:(name:String)->String,noinline area2:(name:String)->String):String
{
return area1("iPhone") + " " + area2("长城")
}
fun main(args: Array<String>)
{
println(process1({name->"${name} 美国"},{name->"${name} 中国"}))
}
输出:
iPhone 美国 长城 中国
@noinline
为了你想要一些 lambda 表达式传递给内联函数时是内联的,你可以给你的一些函数参数标记 ==@noinline== 注解:
inline fun foo(inlined: () -> Uint, @noinline notInlined: () ->
Unit) {
//...
}
内联的 lambda 只能在内联函数中调用,或者作为内联参数,但@noinline标记的可以通过任何我们喜欢的方式操控:存储在字段,(passedaroundetc)
注意如果内联函数没有内联的函数参数并且没有具体类型的参数,编译器会报警告,这样内联函数就没有什么优点的(如果你认为内联是必须的你可以忽略警告)
返回到非局部
在 kotlin 中,我们可以不加条件的使用 return 去退出一个命名函数或表达式函数。这意味这退出一个 lambda 函数,我们不得不使用标签,而且空白的 return在 lambda 函数中是禁止的,因为 lambda 函数不可以造一个闭合函数返回:
fun foo() {
ordinaryFunction {
return // 错误 不可以在这返回
}
}
但如果 lambda 函数是内联传递的,则返回也是可以内联的,因此允许下面这样:
fun foo() {
inlineFunction {
return //
]
}
注意有些内联函数可以调用传递进来的lambda函数,但不是在函数体,而是在另一个执行的上下文中,比如局部对象或者一个嵌套函数。在这样的情形中,非局部的控制流也不允许在lambda 函数中。为了表明,lambda 参数需要有
内联 lambda 不允许用 break 或 continue ,但在以后的版本可能会支持。
内联属性
inline 同样可以用在属性的get和set,但这两个函数不能包含field字段。
class MyClass1234
{
val value:Int
inline get() = 10
public var t:String = ""
var test:String
get() = t
inline set(value)
{
t = value
}
inline var abc:Boolean
get() = true
set(value)
{
}
}
fun main(args: Array<String>)
{
var myClass1234 = MyClass1234()
println(myClass1234.value)
println(myClass1234.test)
println(myClass1234.abc)
}
除了单独内联get和set外,还可以内联整个属性
输出: