Kotlin 学习笔记 五:函数和lambda表达式

注意事项:

1:只要在一个函数的函数体实现中再次调用了函数本身,就是递归函数。递归函数一定要向已知方向进行

2.函数只返回单个表达式,则可以用等号=即可 fun area(x:Double):Double =x,而对于单表达式函数而言,编译器可以自动推断函数的返回值类型,因此也可以改为fun area(x:Double)=x

3.Kotlin允许调用函数时通过名字来传入参数值,因此,Kotlin函数的参数名应该具有更好的语义

4.在某些情况下,程序需要在定义函数时为一个或多个形参指定默认值—这样调用函数时就可以省略该形参,而直接调用该形参的默认值。格式:形参名:形参类型 = 默认值

fun sayHi(name: String ="luotianyou"){}

5.如果在定义函数时,在形参的类型前添加vararg修饰,则表明该参数可以接受多个参数值,多个参数值被当成数组传入

6.Kotlin允许个数可变的形参可以处于形参列表的任意位置(不要求时形参列表的最后一个参数),但Kotlin要求一个函数最多只能带一个个数可变的形参

7.Kotlin函数中的参数不能定义是val,还是var,会默认指定为是val, 不能去修改参数值

8,Kotlin的函数重载也只能通过形参列表进行区分,形参个数不同,形参类型不同都可以算函数重载,但是仅有形参名不同、返回值不同或修饰符不同,则不能算函数重载

9,大部分时候不推荐重载形参个数可变的函数,这样做没有意义且容易导致错误

10.Kotlin支持在函数体内部定义函数,这种函数被称为局部函数,局部函数在默认情况下对外部是隐藏的,其封闭函数也可以返回局部函数,以便程序在其他作用域中使用局部函数

11.Kotlin不是纯粹的面向对象语言,Kotlin的函数也是一等公民,因此函数本身也具有自己的类型,函数类型就像数据类型一样,既可用于定义变量,也可用作函数的形参类型,还可作为函数的返回值类型

12.Kotlin的每个函数都有特定的数据类型,函数类型由函数的形式参数、->和返回值类型组成

13.Kotlin可以使用函数类型可以作为形参类型,也可以使用函数类型作为返回值:参考如下程序

fun map(data:Array<Int>,fn:(Int)->Int):Array<Int>{
    var result =Array<Int>(data.size,{0})
    for(i in data.indices){
        result[i]=fn(data[i])
    }
    return result
}
fun square(n:Int):Int{
    return n*n
}
fun cube(n:Int):Int{
    return n*n*n
}
fun main(args:Array<Int>){
    var data = arrayOf(1,3,5,7,9)
    val size=map(data,::square)
    id_text.text=size[0].toString()}
fun map():(Int)->Int{
    fun cube(n:Int):Int{
        return n*n*n
    }
    
    return ::cube
}
fun main(args:Array<Int>){
    val size=map()
    id_text.text=size(10).toString()}

14.Lambda表达式对于不需要复用的局部函数,可以简化局部函数的写法,因此,Lambda表达式修改上述程序,可以修改为

fun map():(Int)->Int{
    return {n:Int->n*n}
}
fun main(args:Array<String>){
    val size =map()
    println(size(10).toString))
}

Lambda表达式总是被大括号扩着

定义lambda表达式无需fun关键字和函数名

形参列表在->之前声明,参数类型可以省略

函数体放在->之后

函数的最后一个表达式自动被作为lambda表达式的返回值

15.Lambda表达式的脱离

var lambadList = java.util.ArrayList<(Int)->Int>()
fun test(fn:(Int)->Int){
    lambadList.add(fun)}
fun main(args:Array<String>){
    test({it*it})
    test({it*it*it})
    for(i in lambadList.indices){
        println(lambadList[i](i+10))
    }
}

16.调用lambda表达式

val square={n:Int -> n*n}
println(square(5))

17.利用上下文推断类型,上文

var square:(Int)->Int={n->n*n}

18.lambda表达式不仅可以省略形参雷士,而且如果只有一个形参,那么K允许省略lambda表达式的形参名,如果lambda表达式省略的形参名,那么此时->也不需要了,如下

var square:(Int)->Int={it*it}

19.如果函数的最后一个参数时函数类型,而且打算传入一个Lambda表达式作为相应的参数,那么久允许在圆括号之外指定lambda表达式,因此建议将函数类型的形参放在参数列表的最后

20.由于lambda表达式不能指定返回值类型,此时就需要使用匿名函数替代lambda表达式来显示指定返回值类型,如果系统可以推断出匿名函数的形参类型,那么允许省略形参类型

val max=fun(vararg x:Int):Int{
    return x[0]
}

21.匿名函数的本质仍然是函数,因此匿名函数的return则用户返回函数本身,而lambda表达式的return用于返回它所在的函数,而不是返回lambda表达式,下述代码之所以可以在lambda表达式中直接使用return,是因为forEach方法使用了inline修饰,因此它相当于一个内联函数

var list=listOf(3,5,8,9,7,1)        
list.forEach(fun(n){
    println($n)//遍历list集合,打印所有数据
    return
}
list.forEach({n->
    println($n)//只打印一个数组元素
    return
}     

22.***lambda表达式或匿名函数可以访问或修改其所在上下文中的变量和常量,会为这项常量和变量创建一个副本

23.内联函数,先简单说一下高阶函数(为函数传入函数或lambda表达式作为参数)的调用过程。

为被调用的表达式或函数创建一个对象

为被调用的表达式或函数所捕获的变量创建一个副本

在跳转到被调用的表达式或函数所在的地址之前,要先保护现场并记录执行地址;从被调用的表达式或函数地址返回时,要先恢复现场,并按原来保存的地址继续执行,也就是常说的压栈和出栈

为了避免产生函数调用的过程,Kotlin可以使用inline关键字来讲被调用的表达式或函数“嵌入”原来的执行流中,内联函数是以目标代码的增加为代价来节省事件开销的,因此只适合于lambda表达式或函数只包含非常简单的执行代码

 fun main(args:Array<String>){
   var x=map { it*it }
}

    inline fun map(fn:(Int)->Int):Int{
        var x=fn(3)
        return x
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值