kotlin - lambda表达式
使用lambda表达式代替局部函数
lambda表达式可以简化代码。比如现在我们要定义一个函数,根据不同的type来确定返回求平方、求立方、求阶乘的函数的应用。如下代码:
//定义函数,该函数的返回值类型为 Int
fun qetMathFunc(type: String): (Int) -> Int {
when (type) {
//调用局部函数
" square" -> return { n: Int -> n * n }
"cube" -> return { n: Int -> n * n * n }
else -> return { n: Int ->
var result = 1
for (index in 2..n) {
result *= index
}
result
}
}
}
lambda表达式与局部函数的区别
- Lambda 表达式总是被大括号括着
- 定义 Lambda 表达式不需要 fun 关键字,无须指定函数名。
- 形参列表(如果有的话)在->之前声明,参数类型可以省略。
- 函数体(Lambda 表达式执行体)放在->之后。
- 函数的最后一个表达式自动被作为Lambda 表达式的返回值,无须使用 return 关键字。
lambda表达式
lambda表达式语法
Kotlin 提供了简洁的Lambda 表达式语法, Lambda 表达式的标准语法如下:
{(形参列表)->
//0条或者多条执行语句
}
无参数的写法:
val 变量名={操作代码}
有参数的写法:
val/var 变量名: (参数的类型,参数类型,...) -> 返回值类型 = {参数1,参数2,... -> 操作参数的代码 }
可等价于
// 此种写法:即表达式的返回值类型会根据操作的代码自推导出来。
val/var 变量名 = { 参数1:类型,参数2:类型, ... -> 操作参数的代码 }
Lambda表达式与局部函数及其相似,我们在开发中一般用lambda表达式来代替局部函数。Lambda表达式的本质其实还是局部函数。
注意:lambda中的参数是不需要括号的,如果使用括号那就是使用解构。至于什么是解构在《类与对象》中会讲到。
实例讲解
- 无参数的情况
// 源代码
fun test(){ println("无参数") }
// lambda代码
val test = { println("无参数") }
// 调用
test() => 结果为:无参数
无参数的情况时参数可以省略
- 有参数的情况
// 源代码
fun test(a : Int , b : Int) : Int{
return a + b
}
// lambda
val test1 : (Int , Int) -> Int = {a , b -> a + b}
// 或者
val test2 = {a : Int , b : Int -> a + b}
// 调用
test(3,5) => 结果为:8
从代码中可以看出,如果定义变量时指明了参数类型,那么后面的lambda表达式{}里面可以省略参数类型,因为编译器可以从上下文推断出参数的类型。如果编译器不能从上下文中推断出参数类型,那么参数类型必须要指明。
- 作为方法的参数
// lambda
fun test(a : Int , b : ( Int ,Int) -> Int) : Int{
return a + b.invoke(3,5)
}
//调用
test(10,{ num1: Int, num2: Int -> num1 + num2 })
//等价于:
test(10){ num1: Int, num2: Int -> num1 + num2 }
- 从上面的代码可以看出在如果函数的最后一个参数是一个lambda表达式,可以把lambda表达式提出到括号外面。
- b.invoke()等价于b()
- 如果一个lambda表达式作为一个函数的参数时,定义的时候只是指定了这个表达式的参数类型和返回值,所以我们在调用高阶函数的时候要传入该Lambda表达式具体的实现。
**由于lambda表达式只一个功能灵活的代码块,所以我们完全可以把它赋值给一个变量或直接调用lambda表达式。**示例代码如下:
fun main(args: Array<String>) {
//定义一个 Lambda 表达式,并在它后面添加括号来调用该 Lambda 表达式
val result = { base: Int, exponent: Int ->
var result = 1
for (i in 1..exponent) {
result *= base
}
result
}(4, 3)
println(result) //输出 64
}
lambda表达式中的it
定义只有一个参数的匿名函数时,可以省略参数名用it来代替。代码如下:
fun main(args: Array<String>) {
var square: (Int) -> Int = {it * it}
}
lambda表达式与匿名函数的return
- 匿名函数只是一个没有名字的函数,本质上还是一个函数,因此匿名函数的return返回的是匿名函数本身。
- lambda表达式他只是一个代码块return返回的是它所在的函数,而不是lambda表达式。 例如下面代码:
fun main(args: Array<String>) {
var list = listOf(1,2,3,4,5)
//匿名函数
list.forEach(fun(value){
println("元素为:${value}")
return
})
//lambda表达式
list.forEach {
println("元素为:${it}")
return
}
}
lambda表达式打印结果如下:
元素为:1
匿名函数打印的结果:
元素为:1
元素为:2
元素为:3
元素为:4
元素为:5
从上面函数的打印结果可以验证,我们上面所说的结论,lambda表达式中的return直接返回它所在的函数。lambda表达式一般不写return,如果非得在lambda表达式中使用return语句来返回lambda表达式,可以使用如下方式:
list.forEach {
println("元素为:${it}")
return@forEach
}