1. 概述

在 Kotlin 中,将 Long 类型转换为 Int 是一个常见操作。虽然语法上看似简单,但实际使用中存在隐式截断风险,稍不注意就会导致数据错误。本文带你理清转换机制,并提供更安全的替代方案。

2. 使用 toInt() 辅助函数

Kotlin 的 Long 类内置了一个便捷的 toInt() 方法,用于类型转换:

val longValue = 100L
val intValue = longValue.toInt()

✅ 看似 straightforward,但在生产环境中这种写法容易埋雷——它不会抛出异常,而是直接截断超出部分

3. 截断问题(Truncation Problem)

⚠️ 关键点:Long 是 64 位,Int 是 32 位。当 Long 值超出 Int 表示范围(即小于 Int.MIN_VALUE 或大于 Int.MAX_VALUE)时,调用 toInt() 会发生静默截断

官方文档明确说明:

toInt() 返回的是该 Long 值最低有效 32 位所表示的 Int 值。

这意味着:

val bigLong = Int.MAX_VALUE.toLong() + 1
val truncated = bigLong.toInt()

println(bigLong)      // 输出: 2147483648
println(truncated)    // 输出: -2147483648 (符号位被置位)

❌ 这种“绕回”行为极易引发逻辑错误,尤其是在处理 ID、时间戳等关键字段时。

4. 使用扩展函数避免意外截断

为了防止不可预期的截断,我们可以定义一个更安全的扩展函数,显式检查范围:

fun Long.toIntOrNull(): Int? {
    return if (this >= Int.MIN_VALUE && this <= Int.MAX_VALUE) {
        toInt()
    } else {
        null
    }
}

使用示例:

val validLong = 1000L
val invalidLong = 3_000_000_000L

println(validLong.toIntOrNull())   // 输出: 1000
println(invalidLong.toIntOrNull()) // 输出: null

✅ 优势:

  • 明确表达意图:只允许安全转换
  • 返回 null 可触发后续空值处理流程(如抛出自定义异常、打日志、降级处理等)
  • 避免静默数据污染

你也可以根据业务需求返回 Result<Int> 或抛出特定异常:

fun Long.toIntOrThrow(): Int {
    require(this in Int.MIN_RANGE..Int.MAX_RANGE) {
        "Long value $this is out of Int range"
    }
    return toInt()
}

private val Int.MIN_RANGE get() = Int.MIN_VALUE.toLong()
private val Int.MAX_RANGE get() = Int.MAX_VALUE.toLong()

5. 总结

方式 是否推荐 适用场景
longValue.toInt() ❌ 谨慎使用 已知值在范围内,或故意利用截断行为
toIntOrNull() 扩展 ✅ 推荐 安全转换,需处理越界情况
toIntOrThrow() 扩展 ✅ 推荐 强约束场景,越界应视为错误

📌 核心建议:

在涉及数据库 ID、API 参数、配置项等可能超限的场景下,**永远不要直接调用 toInt()**。优先使用带边界检查的封装方法,把“潜在 bug”变成“可控行为”。

所有代码示例均可在 GitHub 获取:https://github.com/baeldung/kotlin-tutorials/tree/master/core-kotlin-modules/core-kotlin-numbers


原始标题:Convert Long to Int