Skip to content

可空性

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"
    }

}
  1. 延迟初始化的属性都是var, 因为需要在构造方法以外的地方修改它的值; 而val属性必须在构造函数中初始化,会被编译成final字段; 如果被lateinit声明的字段在初始化之前就被访问就会得到异常提示还未被初始化. lateinit属性常用于依赖注入.
  2. null对象是可以调用扩展函数的, 因为扩展函数会被编译成静态的Java方法, 需要在扩展函数中检查null

泛型类型

泛型类型参数默认都是可空的,所以在调用的时候需要使用安全调用.

fun <T : Person?> printName(t: T) {
    println(t?.name)
}

原文链接: http://herman7z.site