目录
匿名函数:
- 定义时不取名的函数,我们称之为匿名函数通常整体传递给其他函数,或者从其他函数返回
- 匿名函数对Kotlin来说很重要,有了它,我们可以轻松的给标准库里的内函数定制特殊规则
fun main(){
val total:Int = "Mississippi".count({letter -> letter =='s' })
println(total)
}
匿名函数类型与隐式返回:
匿名函数也有类型,匿名函数可以当作变量赋值给函数类型变量,就像其他变量一样,匿名函数就可以在代码里传递了。变量有类型,变量可以等于函数,函数也有类型的。函数的类型,由传入的参数和返回值类型决定。
和具名函数不一样,处了极少数情况外,匿名函数不需要return关键字来返回数据,匿名函数会隐式或自动返回函数体的最后一行语句的结果
fun main(){
//变量的类型时一个匿名函数
val blessingFunction:()->String
blessingFunction = {
val holiday = "New Year."
"Heppy $holiday"}
//执行匿名函数时不是只写变量名还要在变量名后加个()如果有参数就在括号里传参
println(blessingFunction())
}
函数参数:
和剧名函数一样,具名函数可以不带参数,也可以带一个或多个任何类型的参数,需要带参数时,参数的类型放在匿名函数的类型定义中,参数名则放在函数定义中
fun main(){
//变量的类型时一个匿名函数
val blessingFunction:(String)->String = {name -> //name是随便起的一个变量名类型可以省略,因为lanbada表达式会用到
val holiday = "New Year"
"$name, Happy $holiday"
}
println(blessingFunction("Jack"))
}
it关键字:
定义只有一个参数的匿名函数时,可以使用it关键字来表示参数名。当你需要传入两个值参,it关键字就不能用了。
匿名函数的类型推断:
和下面代码时一样的
类型推断也支持带参数的匿名函数,但为了帮助编译器更准确地推断变量类型,匿名函数的参数名和参数类型必须有
等于下面这个
lambda:
我们将匿名函数称为lambda,把它的定义称为lambda表达式,它返回的数据称为lambda结果。为什么叫lambda? lambda也可以用希腊字符入表示,是lambda演算的简称, lambda演算是一套数理演算逻辑,由数学家Alonzo Church (阿隆佐丘齐)于20世纪30年代发明,在定义匿名函数时,使用了lambda演算记法。
定义函数的参数是另外一个函数:
fun main(){
val getDiscountWords = {goodsName:String, hour:Int ->
val currentYear = 2017
//这个匿名函数最终返回的字符串
"${currentYear}年, 双11${goodsName}促销倒计时: $hour 小时"
}
showOnBoard("沐浴露", getDiscountWords )
}
//定义个函数,其中一个入参是一个匿名函数
fun showOnBoard(goodsName:String,getDiscountWords: (String ,Int)-> String){
val hour: Int = (1..24).shuffled().last()
println(getDiscountWords(goodsName,hour))
}
lamda的简略:
下面解释这玩意,Lambda是一小段可以作为参数传递的代码。正常情况,参数传递的是变量,现在确实一小段代码。其语法结构如下:
{参数名1:参数类型,参数名2:参数类型->函数体}
- 1.因此刚才的问题按照语法结构进行套用:
val lambda = { fruit: String -> fruit.length }
val maxLengthFruit = list.maxBy (lambda )
- 2.首先开始简化,不需要专门定义lambda变量,直接传入。
val maxLengthFruit = list.maxBy ({ fruit: String -> fruit.length } )
- 3.其次Kotlin规定,一个函数的lambda参数排在最后可移到函数括号的外面,如果Lambda 参数是函数唯一参数的话,可以将括号省略。
//lambda参数是唯一参数情况时
val maxLengthFruit = list.maxBy { fruit: String -> fruit.length }
- 4.lambda参数不是唯一参数但是是最后一位参数情况时
fun main(){
showOnBoard("沐浴露" ){goodsName:String, hour:Int ->
val currentYear = 2017
//这个匿名函数最终返回的字符串
"${currentYear}年, 双11${goodsName}促销倒计时: $hour 小时"
}
}
//定义个函数,其中一个入参是一个匿名函数
fun showOnBoard(goodsName:String,getDiscountWords: (String ,Int)-> String){
val hour: Int = (1..24).shuffled().last()
println(getDiscountWords(goodsName,hour))
}
- 5.根据类型推导机制,参数列表不必声明参数类型,因为可以推导。
val maxLengthFruit = list.maxBy { fruit -> fruit.length }
- 6.最后,当参数列表只有一个参数时,不必声明参数名,而是使用it关键字替代。因此变成了
val maxLengthFruit = list.maxBy { it.length }
函数内联:
lambda可以让你更灵活地编写应用,但是,灵活也是要付出代价的。 在JVM上,你定义的lambda会以对象实例的形式存在)JVM会为所有同lambda打交道的变量分配内存,这就产生了内存开销。更糟的是, lambda的内存开销会带来严重的性能问题。幸运的是, kotlin有一种优化机制叫内联,有了内联,JVM就不需要使用lambda对象实例了,因而避免了变量内存分配。哪里需要使用lambda,编译器就会将函数体复制粘贴到哪里。>使用lambda的递归函数无法内联,因为会导致复制粘贴无限循环,编译会发出警告。
简单理解当一个函数参数是lambada对象是不会为其分配内存,而是把它转换成很多语句去执行
函数引用:
要把函数作为参数传给其他函数使用,除了传lambada表达式,kotlin还提供了其他方法,传递函数引用,函数引用可以把一个具名函数转换成一个值参,使用lambada表达式的地方,都可以使用函数引用,使用时要在函数名加::
fun main(){
showOnBoard("牙膏",::getDisountWord)
}
private fun getDisountWord(goodsName: String,hour: Int):String{
val currentYear = 2027
return "${currentYear}年, 双11${goodsName}促销倒计时: $hour 小时"
}
fun showOnBoard(goodsName:String,getDiscountWords: (String ,Int)-> String){
val hour: Int = (1..24).shuffled().last()
println(getDiscountWords(goodsName,hour))
}
函数类型作为返回类型:
函数类型也是有效的返回类型,也就是说可以定义一个能返回函数的函数
package com.example.myapplication
fun main(){
val getDiscoutWords:(String) -> String = configDiscountWords()
println(getDiscoutWords("牙膏"))
//纠结为什么getDiscoutWords就变成getDiscoutWords("牙膏")因为赋值后他就相当于
// val getDiscoutWords:(String) -> String= { goodsName: String ->
// "${currentYear}年,双11${goodsName}促销倒计时:$hour"
//这里的${currentYear}和${goodsName}都是在configDiscountWords()赋好值的
}
}
fun configDiscountWords(): (String) -> String{
val currentYear = 2007
val hour:Int = (1..24).shuffled().last()
return { goodsName: String ->
"${currentYear}年,双11${goodsName}促销倒计时:$hour"
}
}
思考下 configDiscountWords函数下的两个变量为什么匿名函数里依然可以使用,这就叫做作用域共享,具名函数时共享不了的,就涉及到下个知识点
闭包:
在Kotlin中,匿名函数能修改并引用定义在自己的作用域之外的变量,匿名函数引用着定义自身的函数里的变量, Kotlin中的lambda就是闭包。
能接收函数或者返回函数的函数又叫做高级函数,高级函数广泛应用于函数式编程当中。
kotlin文件和文件之间的作用域是同一个作用域所以在main方法外定义一个和别的文件重名的常量(const)会报错,所以在kotlin中一个函数相当于一个类,他会在函数中把作用域处理好
lambda与匿名内部类:
为什么要在代码中使用函数类型?函数类型能让开发者少写模式化代码,写出更灵活的代码。Java 8支持面向对象编程和lambda表达式,但不支持将函数作为参数传给另一个函数或变量,不过Java的替代方案是匿名内部类。