空指针检查
空指针异常是运行时异常,在异常中占较大比例。kotlin语言利用编译时判空检查机制几乎杜绝了空指针异常。
可空类型
Kotlin将空指针异常提前到了编译时期,默认所有的参数和变量都不可为空。
但是在Kotlin中也提供了另外一套可为空的类型系统,在使用这个可为空的类型系统时,我们需要在编译时期就将潜在的空指针异常处理掉,否则编译不通过。
可空类型的写法是在类名后面加?,如
String?
Int?
设置可空类型的参数后,还是使用原来的调用会报错。这个因为判断会造成空指针异常。
判空辅助工具
?.操作符
最常用的?.操作符,含义是当对象不为空时,正常调用,当对象为空时不做处理。
study?.readBook()
等价于
if(study != null) {
study.readBook()
}
?:操作符
这个操作符的左右两边都接收一个表达是,如果左边表达式的结果不为空则返回左边,否则返回右边表达式的结果。
val c = a ?: b
等价于
val c = if (a != null) {
a
} else {
b
}
非空断言工具!!
对于一些我们确定不会为null的,想让其强行编译通过,可以使用非空断言工具
val c = a!!.doSomething()
使用断言会存在风险,如果有其他写法尽量考虑其他写法。
其他特性
字符串内嵌表达式
在Java中,对于字符串拼接变量值使用+号或者构建一个StringBuilder这种类来完成拼接。而在Kotlin中,支持字符串内嵌表达式,可以这样使用
"hello ${person.name},nice to meet you!"
当表达式中只有一个变量的时候,还可以将括号省略
"hello $person.name,nice to meet you!"
函数默认参数值
这个在C++里面是支持的,但在Java中不支持。可以在函数定义的时候给函数的某一个或几个参数设置默认的参数值。当没有传参的时候就使用默认的参数值,如果有传参则使用传入的参数。
fun printParams(num: Int, str: String = "hell0") {
println("num is $num,str is $str")
}
需要注意的是,对于上面的这种默认参数在最后一个的情况,可以在调用的时候只传前面的参数,但是默认参数在第一个的时候,直接传入参数会默认传给第一个参数,这样就会报错。
kotlin针对此,开发出了一种使用键值对来进行传参的机制,让参数一一对应
常用的函数
let函数
该函数提供了函数式API的编程接口,并将原始调用对象作为参数传递到Lambda表达式中。
/**
* Calls the specified function [block] with `this` value as its argument and returns its result.
*
* For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#let).
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
let函数主要配合?.进行使用,可以在外部判断后,如果对象不为空,则将其传入let的lambda表达式之中,处理该对象的多条调用。
fun doStudy() {
study?.let {
it.readBooks()
it.doHomework()
}
}
同时,let函数还可以处理全局变量的判空问题。如果使用if语句则仍然会提示错误,这是因为全局变量随时有可能被其他线程修改,即使做了判空处理,也会有空指针的风险。