之所以我觉得Kotlin有点为了语法糖而语法糖的地方就在这里,一个Lambda表达式有五种写法。。。虽然是一步步根据语法糖演变过来的,但是我还是记的相当痛苦。
- Lambda:一小段可以作为参数传递的代码,语法结构为:
{参数名1: 参数类型,参数名2:参数类型 -> 函数体}
这是完整的Lambda表达式的定义公式,函数体的最后一行代码就是该Lambda表达式的返回值!当然还有简化版的啦,做一个找出 一个数组里长度最长的单词的函数的话,用Lambda表达式应该这么写:
fun main() {
val list = listOf("a", "asd", "dsaf", "sd", "sdfsadfsad", "sdafsdafsadfsafds")
val lambda = { s: String -> s.length }
val result = list.maxBy(lambda)
println(result)
}
首先定义一个数组,随便写几个字符串,然后定义一个Lambda表达式语句,按照刚才完整的公式定义出来的,接下来开始简化,首先不需要定义额外的lambda变量来接收Lambda表达式语句,直接丢进maxBy函数里面就行:
fun main() {
val list = listOf("a", "asd", "dsaf", "sd", "sdfsadfsad", "sdafsdafsadfsafds")
val result = list.maxBy({ s: String -> s.length })
println(result)
}
然后Kotlin规定,当Lambda表达式是该函数的最后一个参数的时候,可以把Lambda表达式移到括号外面:
val result = list.maxBy(){ s: String -> s.length }
接下来,如果Lambda是该函数的唯一一个参数时,可以将括号省略:
val result = list.maxBy{ s: String -> s.length }
然后由于Kotlin有出色的类型推导机制,所以String类型的声明也可以省略:
val result = list.maxBy { s -> s.length }
最后!最终简化版就要来了!如果该Lambda表达式只有一个参数的时候,可以不给形参定义名字,用默认的it关键字来代替:
val result = list.maxBy { it.length }
其实看了之后觉得,嗯。。。还是挺爽的哈哈
- Java函数式API
我举个栗子,在Java中要开启一个子线程的话,需要这么写:
new Thread(new Runnable() {
@Override
public void run() {
doSomething();
}
}).start();
在JDK1.8之后加入了Java的Lambda表达式之后是这样子:
new Thread(() -> {
doSomething();
}).start();
而在Kotlin中呢,,最终简化版是这样的:
Thread{
doSomething()
}
也是由标准的Lambda表达式公式定义,然后一步一步的演变成这么简单的,你可以自己演变一下。
Kotlin还有强大的空指针检查系统,所有的参数默认情况下统统不能为空,Kotlin将空指针的检查提前到了编译期!
但是总是有些地方需要可以为空的参数的,这个时候可以在参数类型后面加个问号:
fun doStudy(study: Study?) {
study.readBooks()
study.doHomework()
}
回到刚才的doStudy方法,在Study后面加个问号,就可以传null了,但是编译会报错:
它说只有?.和非空的调用才被允许,等等,这个?.是个啥??其实是当当前对象不为空的时候才调用后面的方法的意思,这个和我在写Flutter的时候Dart语言一毛一样。说到?.操作符,那不得不提到let函数了,let函数是将原始的调用对象当做参数传到lambda表达式中作为形参,这么说有点绕,举个栗子:
fun doStudy(study: Study?) {
study?.let { obj ->
obj.readBooks()
obj.doHomework()
}
}
这里的lambda表达式里面的obj就是外面的study,明白了吧,这么做的好处就是我只用进行一次?.的调用就可以做到空指针安全了,不为空的情况下才会进入到lambda表达式。
当当前对象为空时,如果你想返回一个默认值的情况下,可以用?:操作符,?:操作符后面的值就是当对象为空的时候的返回值,举个例子:
如果我们传入student对象,那么打印出来的当然就是readBooks()方法的返回值:read books
如果我们传入null的话:
这就是?:的用法,在Dart语言里面则是 ??双问号。
还有一种方法就是强行通过编译,使用!!.操作符:
!!.的意思就是告诉Kotlin,我很确定这个对象不会为空,用不着你来帮我做非空检查,出了问题劳资负责,你直接抛空指针异常吧!