美文网首页
Lambda表达式和成员引用

Lambda表达式和成员引用

作者: Ryan_Hoo | 来源:发表于2018-07-19 21:17 被阅读0次

    1.1、Lambda简介:作为函数参数的代码块

    函数式编程:把函数当做值来对待。可以直接传递函数,而不是先声明一个类在传递这个类的实例。

    1.2、Lambda和集合

    data class Person(val name : String , val age : Int)

    val people = listOf(Person("Alice",29),Person("Bob",31))

    person.maxBy{it.age} //用Lambda在集合中搜索

    //person.maxBy{Person :: age} //lambda刚好是函数或者属性的委托,可以用成员引用替换。

    1.3、Lambda表达式的语法

    Lambda表达式: {x:Int , y: Int -> x+y}

    Kotlin的lambda表达式始终用花括号包围。实参并没有用括号括起来。箭头把实参列表和lambda的函数体隔开。

    可以把lambda表达式存储在一个变量中,把这个变量当做普通的函数对待:

    val  sum  = {x:Int , y: Int -> x+y}

    println( sum(1,2) )


    那么1.2中的例子我们可以改写为:

    people.maxBy({ p: Person -> p.age })

    Kotlin有这样一种语法约定,如果lambda表达式是函数调用的最后一个实参,他可以放到括号的外边。people.maxBy(){ p: Person -> p.age }当lambda是函数的唯一的实参时,还可以去掉调用代码中的空括号对:people.maxBy{ p: Person -> p.age }

    省略lambda参数类型:people.maxBy{ p  -> p.age } //推导出参数类型

    对于不能推到出参数类型的情况,我们可以 先不声明类型,等编译器报错后在指定他们。可以指定部分实参数的类型,而剩下的实参只用名称。

    终极简化 : 使用默认参数名称it代替命名参数。如果当前上下文期望的是只有一个参数的lambda这个参数的类型可以推断出来,就会生成这个名称。

    people.maxBy { it.age }  //仅在实参名称没有显示地指定时这个默认的名称才会生成

    1、不能滥用it,特别是在嵌套lambda的情况,最好显式的声明每个lambda的参数。

    2、用变量存储lambda时,要显式地指定参数类型

    val   getAge = { p : Person -> p.age }

    people.maxBy(getAge)

    1.4、在作用域中访问变量

    fun printlnProblemCounts(responses:Collection<String>){

    var clientErrors =0

        var serverErrors =0

        responses.forEach {

            if (it.startsWith("4")) {

                    clientErrors++

             }else{

                    serverErrors++

             }

        }

    }

    和java比,在kotlin中不会仅限于访问final变量,Kotlin允许在lambda内部访问非final变量甚至修改他们。从lambda内访问外部变量,我们称这些变量被lambda捕捉。例如上面的clientErrors和serverErrors一样。默认情况下局部变量的生命周期别限制在声明的这个变量的函数中,但是如果他被捕捉了,使用这个变量的代码可以被存储并稍后在执行。当你捕捉final变量时,它的值和使用这个值的lambda代码一起存储;而对非final变量来说,它的值被封装在一个特殊的包装器中,这样你哦可以改变这个值,而对于这个包装器的引用会和lambda代码一起存储。

    捕捉可变变量:实现细节

    1、声明一个单元数的数组,其中存储可变值。

    2、创建一个包装器的实例,其中存储要改变的值的引用。

    1.5、成员引用

    Kotlin和Java8一样,如果把函数转换成一个值,你就可以传递它。使用 :: 运算符来转换:

    val  getAge=Person::age    //这种表达式成为成员引用

    使用场景:

    1、引用顶层函数。::函数名

    2、lambda要委托给一个接收多个参数的函数,提供成员引用代替它。

    3、构造方法引用  --- 在冒号后指定类名

    4、引用扩展函数 。

    相关文章

      网友评论

          本文标题:Lambda表达式和成员引用

          本文链接:https://www.haomeiwen.com/subject/ztdipftx.html