Kotlin系列之Lambda表达式完全解析

简述: 今天带来的Kotlin浅谈系列的第六弹, 一起来聊下Kotlin中的lambda表达式。lambda表达式应该都不陌生,在Java8中引入的一个很重要的特性,将开发者从原来繁琐的语法中解放出来,可是很遗憾的是只有Java8版本才能使用。而Kotlin则弥补了这一问题,Kotlin中的lambda表达式与Java混合编程可以支持Java8以下的版本。那我们带着以下几个问题一起来看下Kotli...
摘要由CSDN通过智能技术生成

简述: 今天带来的Kotlin浅谈系列的第六弹, 一起来聊下Kotlin中的lambda表达式。lambda表达式应该都不陌生,在Java8中引入的一个很重要的特性,将开发者从原来繁琐的语法中解放出来,可是很遗憾的是只有Java8版本才能使用。而Kotlin则弥补了这一问题,Kotlin中的lambda表达式与Java混合编程可以支持Java8以下的版本。那我们带着以下几个问题一起来看下Kotlin中lambda表达式。

  • 1、为什么要使用Kotlin的lambda表达式(why)?
  • 2、如何去使用Kotlin的lambda表达式(how)?
  • 3、Kotlin的lambda表达式一般用在哪(where)?
  • 4、Kotlin的lambda表达式的作用域变量和变量捕获
  • 5、Kotlin的lambda表达式的成员引用

一、为什么要使用Kotlin的lambda表达式?

针对以上为什么使用Kotlin中的lambda表达式的问题,我觉得有三点主要的原因。

  • 1、Kotlin的lambda表达式以更加简洁易懂的语法实现功能,使开发者从原有冗余啰嗦的语法声明解放出来。可以使用函数式编程中的过滤、映射、转换等操作符处理集合数据,从而使你的代码更加接近函数式编程的风格。
  • 2、Java8以下的版本不支持Lambda表达式,而Kotlin则兼容与Java8以下版本有很好互操作性,非常适合Java8以下版本与Kotlin混合开发的模式。解决了Java8以下版本不能使用lambda表达式瓶颈。
  • 3、在Java8版本中使用Lambda表达式是有些限制的,它不是真正意义上支持闭包,而Kotlin中lambda才是真正意义的支持闭包实现。(关于这个问题为什么下面会有阐述)

二、Kotlin的lambda表达式基本语法

1、lambda表达式分类

在Kotlin实际上可以把Lambda表达式分为两个大类,一个是普通的lambda表达式,另一个则是带接收者的lambda表达式(功能很强大,之后会有专门分析的博客)。这两种lambda在使用和使用场景也是有很大的不同. 先看下以下两种lambda表达式的类型声明:

针对带接收者的Lambda表达式在Kotlin中标准库函数中也是非常常见的比如with,apply标准函数的声明。

@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
   
    contract {
   
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}

@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
   
    contract {
   
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

看到以上的lambda表达式的分类,你是不是想到之前的扩展函数了,有没有想起之前这张图?

是不是和我们之前博客说普通函数和扩展函数类似。普通的Lambda表达式类似对应普通函数的声明,而带接收者的lambda表达式则类似对应扩展函数。扩展函数就是这种声明接收者类型,然后使用接收者对象调用直接类似成员函数调用,实际内部是通过这个接收者对象实例直接访问它的方法和属性。

2、lambda基本语法

lambda的标准形式基本声明满足三个条件:

含有实际参数

含有函数体(尽管函数体为空,也得声明出来)

以上内部必须被包含在花括号内部

以上是lambda表达式最标准的形式,可能这种标准形式在以后的开发中可能见到比较少,更多是更加的简化形式,下面就是会介绍Lambda表达式简化规则

3、lambda语法简化转换

以后开发中我们更多的是使用简化版本的lambda表达式,因为看到标准的lambda表达式形式还是有些啰嗦,比如实参类型就可以省略,因为Kotlin这门语言支持根据上下文环境智能推导出类型,所以可以省略,摒弃啰嗦的语法,下面是lambda简化规则。

注意:语法简化是把双刃剑,简化固然不错,使用简单方便,但是不能滥用,也需要考虑到代码的可读性.上图中Lambda化简成的最简单形式用it这种,一般在多个Lambda嵌套的时候不建议使用,严重造成代码可读性,到最后估计连开发者都不知道it指代什么了。比如以下代码:

这是Kotlin库中的joinToString扩展函数,最后一个参数是一个接收一个集合元素类型T的参数返回一个CharSequence类型的lambda表达式。

//joinToString内部声明
public fun <T> Iterable<T>.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String {
   
    return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString()
}


fun main(args: Array<String>) {
   
    val num = listOf(1, 2, 3)
    println(num.joinToString(separator = ",", prefix = "<", postfix = ">") {
   
        return@joinToString "index$it"
    })
}

我们可以看到joinToString的调用地方是使用了lambda表达式作为参数的简化形式,将它从圆括号中提出来了。这个确实给调用带来一点小疑惑,因为并没有显示表明lambda表达式应用到哪里,所以不熟悉内部实现的开发者很难理解。对于这种问题,Kotlin实际上给我们提供解决办法,也就是我们之前博客提到过的命名参数。使用命名参数后的代码

//joinToString内部声明
public fun <T> Iterable<T>.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String {
   
    return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString()
}
fun main(args: Array<String>) {
   
    val num = listOf(1, 2, 3)
    println(num.joinToString(separator = ",", prefix = "<", postfix = ">", transform = {
    "index$it" }))
}
4、lambda表达式的返回值

lambda表达式返回值总是返回函数体内部最后一行表达式的值

package com.mikyou.kotlin.lambda

fun main(args: Array<String>) {
   

    val isOddNumber = {
    number: Int ->
        println("number is $number")
        number % 2 == 1
    }

    println(isOddNumber.invoke(100))
}

将函数体内的两个表达式互换位置后

package com.mikyou.kotlin.lambda

fun main(args: Array<String>) {
   

    val isOddNumber = {
    number
  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熊喵先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值