1. 概述
在 Kotlin 中,可空性 是类型系统的核心特性之一,它的存在极大减少了常见的 NullPointerException(NPE)问题。与许多其他编程语言不同,Kotlin 明确区分了可空类型(nullable)和非空类型(non-nullable),要求开发者必须显式处理可能为 null 的情况。
为了利用这套安全的类型系统,我们通过在类型后添加问号 ?
来声明一个变量是可空的。本文重点探讨:✅ 如何从一个可空的 Int?
安全地获取 Int
值。
这在实际开发中非常常见,比如解析 JSON、数据库查询结果或接口返回值时,稍不注意就会踩坑 ❌。
2. 非空断言操作符(!!)
最直接的方式是使用 非空断言操作符(也叫 “double-bang” 或 !!
):
val value: Int? = 10
assertEquals(10, value!!)
顾名思义,这个操作符表示:“我断定这个值一定不为 null”。⚠️ 但如果值确实是 null
,运行时会立即抛出 NullPointerException
:
val value: Int? = null
assertFailsWith<NullPointerException> {
value!!
}
使用建议:
- ✅ 仅当你100%确定值不为空时使用。
- ❌ 否则极易引发线上崩溃,属于“懒人写法”,慎用!
3. Elvis 操作符(?:)
更推荐的做法是使用 Elvis 操作符(?:
),它可以在值为 null 时提供一个默认替代值,从而安全转换为非空类型。
语法结构如下:
val result = nullableValue ?: defaultValue
示例:
val value: Int? = null
assertEquals(0, value ?: 0) // 提供默认值 0
如果原始值非空,则直接使用原值:
val value: Int? = 10
assertEquals(10, value ?: 0) // 默认值被忽略
优势:
- ✅ 安全可靠,避免 NPE
- ✅ 代码简洁,语义清晰
- ✅ 适合大多数业务场景下的空值兜底
实际应用举例:
fun getUserAge(userId: String): Int {
val ageFromDb: Int? = database.findAgeByUserId(userId)
return ageFromDb ?: -1 // 查不到时返回 -1 表示未知
}
这种写法在 DAO 层或配置读取中非常实用,能有效防止因数据缺失导致的服务中断。
4. 总结
本文介绍了两种将 Int?
转换为 Int
的常用方式:
方法 | 操作符 | 是否安全 | 适用场景 |
---|---|---|---|
非空断言 | !! |
❌ 不安全 | 确认非空的极端情况 |
Elvis 操作符 | ?: |
✅ 安全 | 绝大多数日常开发 |
✅ 推荐优先使用 Elvis 操作符进行空值处理,提升代码健壮性。
❌ 尽量避免滥用 !!
,尤其是在不可控的数据源场景下,否则容易埋下隐患。
📌 核心原则:让 null 的处理变得显式且可控,而不是依赖运气。