Kotlin 中的 ?. 和 . 语法详解
一句话总结
| 语法 | 名称 | 作用 |
|---|---|---|
. |
成员访问操作符 | 直接访问对象的属性或方法 |
?. |
安全调用操作符 | 对象不为 null 时才访问,为 null 则返回 null |
1. . 成员访问操作符(普通调用)
这是最基础的语法,和 Java、Python 等语言一样,用来访问对象的属性和方法:
kotlin
val name: String = "Kotlin"
// 用 . 访问属性
println(name.length) // 6
// 用 . 调用方法
println(name.uppercase()) // KOTLIN
但是,如果对象可能为 null:
kotlin
val name: String? = null // 可空类型
// name.length // ❌ 编译错误!可空类型不能直接用 . 调用
编译器会直接报错,不让你编译通过 ,因为如果 name 是 null,调用 .length 就会空指针崩溃。
2. ?. 安全调用操作符(Safe Call)
?. 就是为了解决上面的问题而设计的,它的逻辑很简单:
如果对象不为 null → 正常调用;如果为 null → 直接返回 null,不崩溃
kotlin
val name: String? = null
val length: Int? = name?.length
// name 是 null → 不调用 .length → 直接返回 null
println(length) // null(没有崩溃!)
kotlin
val name: String? = "Kotlin"
val length: Int? = name?.length
// name 不是 null → 正常调用 .length
println(length) // 6
3. 直观对比
kotlin
val user: User? = null
// ❌ 用 . ------ 编译器直接报错,不让你这样写
// user.name
// ✅ 用 ?. ------ 安全,返回 null
user?.name // 结果是 null
// ✅ 用 . ------ 但前提是类型不可空
val user2: User = User("Alice")
user2.name // 结果是 "Alice"
你可以把 ?. 理解为一个简写:
kotlin
// 这两种写法完全等价:
// 写法1:用 ?.
val result = user?.name
// 写法2:手动判断 null
val result = if (user != null) {
user.name
} else {
null
}
4. ?. 链式调用
?. 最强大的地方是可以链式使用,任何一环为 null 就直接短路返回 null:
kotlin
class Address(val city: String?)
class Company(val address: Address?)
class User(val company: Company?)
val user: User? = User(Company(Address("北京")))
// 链式安全调用
val city: String? = user?.company?.address?.city
println(city) // 北京
// 任何一环为 null,整个结果就是 null
val user2: User? = User(Company(null))
val city2: String? = user2?.company?.address?.city
println(city2) // null(address 是 null,后面就不再调用了)
如果不用 ?.,你需要写大量嵌套判断:
kotlin
// 不用 ?.(又丑又长)
val city = if (user != null) {
if (user.company != null) {
if (user.company.address != null) {
user.company.address.city
} else null
} else null
} else null
5. 常见搭配
搭配 ?: (Elvis 操作符)------ 给个默认值
kotlin
val name: String? = null
// 如果 name 为 null,就用 "未知" 代替
val displayName = name ?: "未知"
println(displayName) // 未知
// 组合使用
val length = name?.length ?: 0
println(length) // 0
搭配 ?.let ------ 不为 null 时执行代码块
kotlin
val email: String? = "hello@kotlin.org"
email?.let {
println("发送邮件到: $it") // 只有 email 不为 null 才执行
}
6. 总结图示
对象.属性 ← 普通调用,对象必须非空
对象?.属性 ← 安全调用,对象可空
┌─ 不为 null → 正常调用,返回结果
对象?.属性 ─────┤
└─ 为 null → 跳过调用,返回 null
一句话记忆:
.是"我确定它不是 null,直接访问"
?.是"它可能是 null,帮我安全地试一下"
后记
2026年5月18日于上海,在claude opus 4.6辅助下完成。