安全调用(?.)
安全调用运算符允许开发者在可能为空的对象上安全地访问属性或调用方法。如果对象不为空,操作就会被执行;如果对象为空,则跳过操作,并返回null而不是抛出NullPointerException。
val length = text?.length
如果text不为null,那么length将被赋予text的长度;如果text为null,那么length也将为null,全部都不会报NullPointerException。
data class Department(val head: Manager?)
data class Manager(val name: String, val assistant: Assistant?)
data class Assistant(val name: String)
fun getAssistantName(department: Department?): String? {
// Accesses the name of the assistant of the department head, if all references are non-null
return department?.head?.assistant?.name
}
还可以链式地进行安全调用,如上面的例子:只有在助理assistant、经理head和部门department都不为空的情况下,才会返回助理的名字assistant?.name
Elvis运算符(?:)
Kotlin还引入了Elvis运算符(?:),该运算符提供了一种简明方式来处理在安全调用或任何可为空表达式后的null情况,允许开发者指定一个默认值或替代表达式,以便在前面的表达式评估为null时使用。
val nameLength = person?.name?.length ?: 0
在上面的例子中,如果person或person.name为null,那么而不是返回null,而是求值于?:之前的表达式,并将nameLength设为0。
?. 与 ?: 结合使用
有许多情景下可以结合两者,以实现更简短、可读且安全的代码库。
即 如果不为空,返回语句返回实际数值 如果为空返回语句返回一个自定义的默认值(就不要返回null) .
无论你何时何地使用它们,Kotlin的安全调用运算符(?.)和Elvis运算符(?:)都会简化对null的处理,提高代码的安全性和清晰度。
安全调用运算符通过为null引用返回null来防止NullPointerException,而Elvis运算符在这种情况下提供默认值。两者共同减少了与null相关的错误,并简化了代码,使Kotlin的开发更加高效和直接。
用于对象的非空判断
如下面的例子:如果助理assistant、经理head和部门department都不为空的情况下,才会返回助理的名字assistant?.name, 如果有一个对象为null,则返回自定义默认值 "No Manager"
fun getManagerName(department: Department?): String {
// Returns the department head's name or "No Manager" if null
return department?.head?.name ?: "No Manager"
}
用于集合元素的非空判断
也可以在可能包含null元素的集合中使用,或者当集合本身可能为null时:
如果集合的元素name存在 则返回元素name的长度值name?.length
如果集合的元素name不存在(为null),则返回自定义的默认值"null"
val listOfNames: List<String?> = listOf("Alice", null, "Bob", "Carol")
// Prints the length of each name, skipping nulls
listOfNames.forEach { name ->
println(name?.length ?: "null")
}
用于类型转换非空判断
在类型转换时,可以使用安全类型转换运算符(as?),它可以与安全调用运算符结合来安全地尝试类型转换,然后在转换类型上执行操作。
val obj: Any = "This is a string"
// Safely casts obj to a String and then calls length, else returns null if cast fails
val length = (obj as? String)?.length