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 的处理变得显式且可控,而不是依赖运气


原始标题:Converting an Int? to an Int in Kotlin