可空性
Kotlin允许对变量声明是否能够为空,如果某个变量被定义成可空,那么调用这个变量就是不安全的,可能会出现NullpointerException, 所以Kotlin在编译期间就会检查.
定义允许变量为空,是在类型后面添加?
val name:String?
注意: 没有问号的变量是不能够设置为null, 这说明Kotlin默认变量就是不能为空
安全调用运算符
在Java中,如果一个对象可能为空,那么我们在调用之前需要先判断是这个对象是否为空,比如下面的例子:
fun toUppercase(name: String?): String? {
if (name == null) {
return null
} else {
return name.uppercase()
}
}
上面的例子Koltin可以使用安全调用运算符 ?.
来简写
fun toUppercase(name: String?): String? {
return name?.uppercase()
}
允许多个安全调用链接调用
name?.uppercase()?.substring(0)
Elvis运算符
在上面的例子,使用了?.
安全调用后,如果是空就会返回null, 若你需要返回一个指定的默认值就可以使用Elvis运算符 ?:
; Elvis运算符通常和安全调用一起使用
fun toUppercase(name: String?): String? {
return name?.uppercase() ?: "NONE"
}
安全转换
Kotlin中类型转换使用 as
关键字, 如果出现了类型不匹配的时候就会抛出ClassCastException
, 当然也可以是用is
来检查类型是否合适. 还有一种简洁的方式就是 as?
, 如果类型不匹配就会返回null; 通常也是和Elvis运算符一起使用
fun toUppercase(name: Any?): String? {
return name as? String ?: "NONE"
}
非空断言
有时候想要把变量转换成非空变量,可以使用!!
, 如果变量的值确实是null, 那么就会抛出异常 NullPointerExcetpion
, 慎用
fun toUppercase(name: String?): String? {
return name!!.uppercase()
}
let函数
假如我们这里有一个方法发送消息函数, msg参数是非空参数
fun sendMsg(msg:String){
// ...
}
当我们把可空的参数传递给这个函数就会编译报错,必须显示的判断参数是否为空
var msg: String? = "Test"
if (msg != null) {
sendMsg(msg)
}
除了上面的这种写法还可以使用let函数来改写
msg?.let { sendMsg(it) }
延迟初始化属性
Koltin通常要求你在构造方法中初始化所有的属性,如果有个属性是非空类型,你就必须提供非空的初始化值,否则就必须使用可空类型. 如果这样做,该属性每次访问的时候都需要if 进行 null检查 或者使用 !!
运算符
为了解决这个问题Kotlin提供了关键字 lateinit
class Person(val name: String, val age: Int) {
private lateinit var address: String
fun setUp() {
address = "Beijing"
}
}
- 延迟初始化的属性都是
var
, 因为需要在构造方法以外的地方修改它的值; 而val
属性必须在构造函数中初始化,会被编译成final字段; 如果被lateinit
声明的字段在初始化之前就被访问就会得到异常提示还未被初始化.lateinit
属性常用于依赖注入.- null对象是可以调用扩展函数的, 因为扩展函数会被编译成静态的Java方法, 需要在扩展函数中检查null
泛型类型
泛型类型参数默认都是可空的,所以在调用的时候需要使用安全调用.
fun <T : Person?> printName(t: T) {
println(t?.name)
}
原文链接: http://herman7z.site