在编程中,lambda表达式是一个匿名函数,它被写成一个表达式。
由于lambda是一个表达式,它可以作为一个参数传递给一个函数或作为一个函数执行的返回值。
许多编程语言都有自己的lambda表达式语法。在Kotlin中,lambda表达式的语法如下:
var [name] : [input type(s)] -> [output type] = { [arguments] -> [body] }
上面的语法可能会让你感到困惑,所以让我们看看Kotlin lambda表达式的一个有效例子。
考虑下面这个makeUppercase() 函数:
var makeUppercase : (String) -> String = { str -> str.uppercase() }
现在让我解释一下上面的例子。
上面的lambda表达式的名字是makeUppercase 。
: (String) -> String 语法意味着该函数接受一个类型为String 的输入,并同时返回一个类型为String 的值。
{ str -> str.uppercase() } 语法是lambda表达式的主体。在这种情况下,输入参数被命名为str 。你不需要明确地声明str 的类型,因为它已经在[input type] 语法中声明了。
表达式的主体只是调用String 实例的.uppercase() 方法。
现在你已经定义了一个lambda表达式,你可以像其他函数一样调用makeUppercase() :
makeUppercase("nathan") // NATHAN
makeUppercase("sarah") // SARAH
lambda表达式需要明确地定义一个返回类型。当你想不返回任何东西时,你可以将返回类型定义为Unit
var makeUppercase: (String) -> Unit = { str ->
println(str.uppercase())
}
当你需要为你的lambda表达式定义多个参数时,你可以添加用逗号分隔的参数类型。
下面的例子创建了一个接受3个参数的lambda表达式:一个String ,一个Int ,和一个Boolean :
var myLambda: (String, Int, Boolean) -> Unit = { str, num, bool ->
println("$str $num $bool")
}
myLambda("nathan", 1, true) // nathan 1 true
另外,你可以将λ表达式的输入和输出类型定义从= 符号的左边移到右边,如下所示:
val makeUppercase = { str: String -> str.uppercase() }
在上面的例子中,参数类型被定义为String ,而返回类型是由lambda主体推断出来的。
it 关键字
当你的lambda表达式只包含一个参数时,你可以使用it 关键字来指代那个参数,而不是你定义的自定义名称。
考虑一下下面的例子:
val plusTwo : (Int) -> Int = { it + 2 }
plusTwo(4) // 6
在上面的plusTwo() 函数中,单个输入参数被称为it ,所以你不需要在大括号内定义参数列表{} 。
it 关键字将永远指代你传入函数的单一参数,所以当它是一个String ,你可以在关键字上调用String 方法:
val makeUppercase : (String) -> String = { it.uppercase() }
请记住,当你的lambda表达式有一个以上的参数时,it 关键字将抛出一个unresolved reference 错误。
把lambda表达式写在圆括号外。
当你把lambda表达式作为函数调用的最后一个参数传递时,你可以把表达式写在包含参数的括号外。
例如,当使用Array 类构造函数创建一个数组时:
val myArray = Array(3) { i -> i * 2 }
// equals to
val myArray = Array(3, { i -> i * 2 })
带有函数指针的Kotlin lambda
最后,当你的lambda表达式主体只有一个函数调用时,你可以使用函数指针语法(::)来调用该函数,而不是正常的.functionName() 。
看一下下面的例子:
val makeUppercase: (String) -> String = String::uppercase
使用函数指针,你可以去掉大括号{} ,lambda主体就变成了一个单一的::uppercase 调用。
Kotlin lambda的常见例子
Kotlin lambda表达式通常在你调用一个需要一个函数作为参数的函数时使用。
例如,用于迭代一个值的forEach 方法接受一个lambda表达式,如下所示:
val name = "Nathan"
name.forEach { c -> print(c) } // Nathan
当你调用Array 方法时,也需要一个lambda表达式,比如map 和 reduce:
val numbers = arrayOf(1, 2, 3)
val newNumbers = numbers.map { n -> n + 2 }
newNumbers.toString() // [3, 4, 5]
val aSum = numbers.reduce { accumulator, currentEl ->
accumulator + currentEl
}
aSum.toString() // 1 + 2 + 3 = 6
当你创建一个Android应用程序时,你可能也会使用lambda表达式作为监听器的主体。
例如,这里是一个AndroidButton ,它的setOnClickListener lambda表达式。
val button = findViewById<Button>(R.id.my_button)
button.setOnClickListener {
Toast.makeText(this, "Hello", Toast.LENGTH_SHORT).show()
}
现在你已经学会了λ表达式在Kotlin中的工作方式。干得好!👍