Lambda表达式:让代码会说话
Lambda表达式,说白了就是一段可以到处传递的代码块。我刚开始接触Kotlin时,就被这种写法惊艳到了——原来代码可以写得这么「像人话」。
你想想看,在Java里写个点击监听器,要new一个匿名内部类,啰嗦得很。Kotlin的Lambda,几行就搞定。我个人习惯把Lambda看作「轻量级的函数快递」——把行为打包,送到需要的地方去执行。
Lambda语法:最简形式
Lambda的基本语法长这样:
// 完整写法
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
// 类型推断后
val sum = { x: Int, y: Int -> x + y }
// 最简形式
val sum = { x, y -> x + y }
箭头左边是参数,右边是函数体。最后一行表达式就是返回值。嗯,这里要注意:Lambda没有return关键字,最后一行自动返回。
核心要点:Lambda表达式用花括号包裹,参数和函数体用->分隔。如果参数只有一个,可以省略参数声明,直接用it。
Lambda作为参数:传递行为
这才是Lambda的真正威力。你可以把一段逻辑当作参数传给另一个函数。我在项目中遇到过很多场景,比如列表过滤、数据转换,用Lambda写起来行云流水。
// 定义一个接受Lambda的函数
fun processNumbers(numbers: List<Int>, operation: (Int) -> Int): List<Int> {
return numbers.map { operation(it) }
}
// 调用时传入Lambda
val result = processNumbers(listOf(1, 2, 3)) { it * 2 }
println(result) // [2, 4, 6]
为什么会这样?因为Kotlin有个约定:如果Lambda是函数的最后一个参数,可以把它写在括号外面。这就是「尾Lambda语法」。你想想看,这样写出来的代码,读起来就像在说「处理这些数字,每个都乘以2」。
我的习惯:如果Lambda参数很长,我通常会把它单独拎出来,放在括号后面。这样代码结构更清晰,可读性更好。
it关键字:隐式参数
当Lambda只有一个参数时,Kotlin允许你省略参数声明,直接用it来引用它。这玩意儿用起来特别顺手,但也容易让人迷糊。
// 显式参数
val doubled = listOf(1, 2, 3).map { number -> number * 2 }
// 使用it
val doubled = listOf(1, 2, 3).map { it * 2 }
// 多层嵌套时,it会让人困惑
val nested = listOf(1, 2, 3).map {
listOf(4, 5, 6).map {
// 这里的it指的是内层Lambda的参数
it + it
}
}
我曾经踩过的坑:在嵌套Lambda里滥用it,结果代码读起来像天书。后来我定了个规矩:嵌套超过一层,必须显式命名参数。别偷懒,不然三个月后你自己都看不懂。
Lambda与匿名函数:同根不同命
匿名函数和Lambda很像,但有几个关键区别。我刚开始学的时候也搞混过,后来才摸清楚门道。
| 特性 | Lambda | 匿名函数 |
|---|---|---|
| 语法 | { x -> x + 1 } |
fun(x: Int): Int { return x + 1 } |
| 返回值 | 最后一行自动返回 | 需要显式return |
| 参数类型 | 可推断时省略 | 通常需要声明 |
| 使用场景 | 简短逻辑,一行搞定 | 复杂逻辑,需要多个return |
// Lambda写法
val lambda: (Int) -> Int = { x ->
if (x > 0) x * 2 else 0
}
// 匿名函数写法
val anonymous: (Int) -> Int = fun(x: Int): Int {
if (x > 0) return x * 2
return 0
}
我个人更偏爱Lambda,因为它简洁。但如果你需要多个return点,或者逻辑比较复杂,匿名函数会更清晰。说白了,选哪个取决于场景——没有银弹。
避坑指南:Lambda里的return行为比较特殊。在Lambda里写return,它会从外层函数返回,而不是只退出Lambda。这就是「非局部返回」。如果你只想退出Lambda,要用标签:return@label。我曾经因为这个bug排查了一下午,印象深刻。
实战:用Lambda重构代码
来看一个真实场景。假设你要处理用户列表,筛选出活跃用户,然后提取他们的名字。
// 传统写法
fun getActiveUserNames(users: List<User>): List<String> {
val result = mutableListOf<String>()
for (user in users) {
if (user.isActive) {
result.add(user.name)
}
}
return result
}
// Lambda写法
fun getActiveUserNames(users: List<User>): List<String> {
return users.filter { it.isActive }
.map { it.name }
}
你想想看,第二种写法是不是像在读英文句子?「过滤出活跃的,然后映射出名字」。这就是Lambda的魅力——让代码从「告诉计算机怎么做」变成「告诉计算机你想要什么」。
嗯,到这里Lambda的基础就讲完了。下一章我们会深入高阶函数,看看Lambda还能玩出什么花样。记住,多写多练,Lambda用顺手了,你会爱上这种表达方式的。