Kotlin-高阶函数,Lambda表达式,内联函数

高阶函数以及Lambda表达式的使用

Kotlin中的函数属于一等公民,它可以被存储在变量中,也可以作为参数传递给高阶函数(将函数作为参数或者返回值的函数)并从中返回

 var func: (Int)->Unit

变量func就表示一个参数为Int类型,没有返回值的函数

我们还可以为函数类型起别名来缩短名称

typealias LambdaExample = (Int)->Unit

fun main(){
    var func: LambdaExample
}

可以使用::来引用一个现成的函数

fun main(){
    var func: (String) -> Int = ::test
    println(func(""))
}

fun test(str: String): Int {
    return 666
}

在这里插入图片描述
还可以直接用匿名函数实现

fun main(){
    var func: (String) -> Int = fun(str: String): Int {
        return 10
    }
    println(func(""))
}

简写成:

fun main(){
    var func: (String) -> Int = fun(str: String): Int = 10
    println(func(""))
}

使用Lambda的方式:

fun main(){
    var func: (String) -> Int = { 
        10
    }
    println(func(""))
}

Lambda默认最后一行作为它的返回值,而且只有一个参数的情况下那个参数为 it (如果是匿名函数直接用参数名就行了)

fun main(){
    var func: (String) -> Int = {
        println(it)
        10
    }
    println(func("hello"))
}

在这里插入图片描述

fun main(){
    var func: (String) -> Int = {
        println("获取到参数$it")
        10
    }
    println(func("hello"))
}

在这里插入图片描述

如果有两个参数的话,就需要手动指定参数的名字

fun main(){
    var func: (String, String) -> Int = { a,b->
        println(a)
        println(b)
        10
    }
    println(func("hello", "Kotlin"))
}

在这里插入图片描述
如果我们不想用第一个参数,就设置成_表示不使用

fun main(){
    var func: (String, String) -> Int = { _,b->
        println(b)
        10
    }
    println(func("hello", "Kotlin"))
}

在这里插入图片描述
高阶函数的Lambda使用

fun test(func: (String) -> Int){
    println(func("hello"))
}

fun main(){
    test { 
        println(it)
        20
    }
}

在这里插入图片描述

更复杂的情况:

fun test(a: Int, b: String, func: (String) -> Int){
    println(a)
    println(b)
    println(func("hello"))
}

fun main(){
    test (10, "abc") {
        println(it)
        20
    }
}

在这里插入图片描述

fun test(a: Int, func: (String) -> Int, b: String){
    println(a)
    println(b)
    println(func("hello"))
}

fun main(){
    test (10,  {
        println(it)
        20
    }, "abc")
}

在这里插入图片描述
最后需要注意的是,在Lambda中没有办法直接使用 return 语句返回结果,而是需要用标签

fun main(){
    val func: (Int) -> String = test@{
        if(it > 10) return@test "我是提前返回结果"
        println("我是正常情况")
        "收到的参数为$it"
    }
    println(func(1))
    println()
    println(func(11))
}

在这里插入图片描述
如果函数调用的尾随Lambda表达式,默认的标签名字就是函数的名字

fun test(func: (Int) -> String) {
    println(func(11))
    println()
    println(func(10))
}

fun main(){
    test {
        if(it > 10) return@test "我是提前返回结果"
        println("我是正常情况")
        "收到的参数为$it"
    }
}

在这里插入图片描述

内联函数

在Kotlin中,使用高阶函数可能会影响运行时的性能: 每个函数都是一个对象, 而且函数内可以访问一些局部变量,这可能造成额外开销

为了优化性能,开销可以通过内联函数来消除。使用inline关键字能让方法的调用在编译时,直接替换为方法的执行代码,比如说下面的这段代码:

fun main() {
    test()
}

//添加 inline 表示内联函数
inline fun test(){
    println("这是一个内联函数")
    println("这是一个内联函数")
    println("这是一个内联函数")
}

由于test函数是内联函数,在编译之后,会原封不动地把代码搬过去

fun main() {
    println("这是一个内联函数")
    println("这是一个内联函数")
    println("这是一个内联函数")
}

同样的,如果是一个高阶函数,效果就更好了:

fun main(){
    test { println("打印: $it") }
}

inline fun test(func: (String) -> Unit) {
    println("这是一个内联函数")
    func("hello word")
}

由于test函数是内联的高阶函数,在编译之后,不仅会原封不动地把代码搬过去,还会自动将传入的函数参数贴到调用的位置

fun main(){
    println("这是一个内联函数")
    val it = "hello word"
    println("打印: $it")
}

内联会导致编译出来的代码变多,但是换来了性能上的提升,不过这种操作仅对高阶函数有显著效果,普通函数实际上完全没有内联的必要,也提升不了多少性能

注意,内联函数默认会将参数也进行内联。内联的函数形参,无法作为值给到变量,只能调用:
在这里插入图片描述
使用noinline修饰符可以禁止参数的内联关系

fun main(){
    test { println("打印: $it") }
}

inline fun test(noinline func: (String) -> Unit) {
    println("这是一个内联函数")
    func("hello word")
    val a = func
}

同样的,由于内联,导致代码被直接搬运,所以Lambda中的return语句可以不带标签,但这种情况可能会导致直接返回:

fun main(){
    test {
        if (it == "hello word") return
        println("打印: $it")
    }
    println("程序结束")
}

inline fun test(func: (String) -> Unit) {
    println("这是一个内联函数")
    func("hello word")
}

在这里插入图片描述

fun main(){
    test {
        if (it == "hello word") return@test
        println("打印: $it")
    }
    println("程序结束")
}

inline fun test(func: (String) -> Unit) {
    println("这是一个内联函数")
    func("hello word")
    println("test结束")
}

在这里插入图片描述
这语法太糖了,@test就作用到func,test函数剩下的部分正常执行

内联函数的优势

  1. 减少内存消耗:内联函数避免了创建Lambda表达式的额外对象,从而减少了内存消耗。
  2. 提升性能:通过将函数体的代码直接复制到调用处,内联函数避免了函数调用的开销,从而提高了程序的性能。
  3. 简化代码结构:内联函数可以直接在调用处展开,使代码更加简洁、紧凑,提高了可读性和可维护性。

注意事项

  1. 慎重选择内联函数:内联函数适用于函数体较小的情况,如果函数体过大,内联将导致代码膨胀,可能会增加可执行代码的大小。
  2. 禁止内联的情况:某些情况下,我们可能不希望函数内联,例如递归函数、高阶函数的参数会被存储在变量中并多次调用的情况。在这种情况下,可以使用noinline修饰符来禁止参数的内联关系。

总结

内联函数是Kotlin中提供的一种优化性能的机制,通过将函数体的代码直接复制到调用处,减少了Lambda表达式的额外对象创建和函数调用的开销。使用内联函数可以提高程序的性能,并简化代码结构。然而,需要慎重选择内联函数,并注意在必要的情况下使用noinline修饰符来禁止参数的内联关系。

### Kotlin 中使用高阶函数实现回调 #### 高阶函数简介 在 Kotlin 中,高阶函数是指接受其他函数作为参数或将函数作为返回值的函数。这种特性使得编写灵活且可重用的代码变得容易。 #### 回调机制概述 通过传递一个函数给另一个函数,在特定事件发生时执行该函数来实现回调功能。这种方式不仅简化了异步编程模型中的复杂度,还提高了代码的可读性和维护性[^1]。 #### 示例:使用高阶函数实现简单回调 下面是一个简单的例子,展示了如何利用高阶函数创建带有回调的功能: ```kotlin // 定义一个名为 `show` 的高阶函数,它接收两个参数: // 一个是布尔类型的变量 isShow, // 另外一个是接受字符串并返回字符串的 Lambda 表达式 callback。 fun show(isShow: Boolean, callback: (String) -> String) { if (isShow) { val result = callback("高阶 show") // 执行传入的Lambda表达式,并传入指定的消息 println("高阶函数返回结果:$result") } } ``` 这段代码定义了一个叫做 `show` 的高阶函数,它可以依据条件决定是否要触发回调逻辑。当 `isShow` 参数为真时,则会调用传入的 `callback` 函数并将消息 `"高阶 show"` 发送给这个函数处理[^3]。 为了测试上述方法的效果,可以通过如下方式调用: ```kotlin val messageProcessor: (String) -> String = { input -> "Processed Message from $input" } show(true, messageProcessor) ``` 这里定义了一个匿名函数 `messageProcessor` 来加工接收到的信息,之后将其作为第二个实参传递给了 `show()` 方法。如果第一个参数设置为 true ,那么就会看到控制台打印出经过加工后的信息:“高阶函数返回结果: Processed Message from 高阶 show”。 #### 性能优化建议 对于频繁使用的高阶函数及其内部的小型 lambda 表达式来说,考虑采用内联技术能够有效降低运行期开销。因为内联可以让编译器把实际调用位置替换成具体的实现体,从而避免额外的方法调用成本[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值