Kotlin 类型转换 #

一、类型转换概述 #

Kotlin 是强类型语言,不支持隐式类型转换,需要显式进行类型转换。

1.1 与 Java 的区别 #

java
// Java:隐式转换
int a = 100;
long b = a;  // 自动转换
kotlin
// Kotlin:需要显式转换
val a: Int = 100
// val b: Long = a  // 编译错误
val b: Long = a.toLong()  // 正确

二、数值类型转换 #

2.1 转换函数 #

所有数值类型都提供转换函数:

kotlin
val int = 100

int.toByte()
int.toShort()
int.toInt()
int.toLong()
int.toFloat()
int.toDouble()
int.toChar()

2.2 转换示例 #

kotlin
val a: Int = 100
val b: Long = a.toLong()
val c: Double = b.toDouble()
val d: Float = c.toFloat()
val e: Int = d.toInt()

2.3 精度丢失 #

kotlin
val long: Long = 1000000000000L
val int: Int = long.toInt()  // 精度丢失

println(int)  // -727379968(溢出)

// 安全转换
val safeInt = long.coerceIn(Int.MIN_VALUE, Int.MAX_VALUE).toInt()

2.4 自动类型提升 #

运算时会自动提升类型:

kotlin
val a: Int = 10
val b: Long = 20L

val sum = a + b       // Long
val product = a * b   // Long

val c: Float = 1.5f
val d: Double = 2.5

val result = c + d    // Double

三、类型检查 #

3.1 is 操作符 #

使用 is 检查类型:

kotlin
val obj: Any = "Hello"

if (obj is String) {
    println(obj.length)  // 智能转换为 String
}

// 否定形式
if (obj !is String) {
    println("Not a String")
}

3.2 when 中的类型检查 #

kotlin
fun process(obj: Any) {
    when (obj) {
        is Int -> println("Integer: $obj")
        is String -> println("String: ${obj.length}")
        is List<*> -> println("List: ${obj.size}")
        else -> println("Unknown type")
    }
}

3.3 类型检查的限制 #

kotlin
// 不能检查泛型参数的具体类型
val list: List<String> = listOf("A", "B")

// 错误:泛型擦除
// if (list is List<String>) { }

// 正确:检查星投影
if (list is List<*>) {
    println("It's a List")
}

四、智能类型转换 #

4.1 基本用法 #

Kotlin 编译器会自动进行智能类型转换:

kotlin
val obj: Any = "Hello"

if (obj is String) {
    // obj 自动转换为 String 类型
    println(obj.uppercase())
    println(obj.length)
}

4.2 智能转换的条件 #

kotlin
// val 局部变量
val obj: Any = "Hello"
if (obj is String) {
    println(obj.length)  // 正确
}

// var 局部变量(编译器无法保证)
var obj2: Any = "Hello"
if (obj2 is String) {
    // 可能需要额外检查
    println(obj2.length)
}

// 类属性(val 且没有自定义 getter)
class Person(val name: Any) {
    fun print() {
        if (name is String) {
            println(name.length)  // 正确
        }
    }
}

4.3 智能转换场景 #

kotlin
// if 语句
if (obj is String) {
    println(obj.length)
}

// when 语句
when (obj) {
    is String -> println(obj.length)
    is Int -> println(obj * 2)
}

// while 循环
while (obj !is String) {
    // ...
}

// 逻辑表达式
if (obj is String && obj.length > 5) {
    println(obj.uppercase())
}

// 提前返回
if (obj !is String) return
println(obj.length)  // 智能转换

五、类型转换操作符 #

5.1 不安全转换 as #

as 进行不安全转换,失败时抛出异常:

kotlin
val obj: Any = "Hello"

val str: String = obj as String  // 成功

val num: Int = obj as Int  // ClassCastException

5.2 安全转换 as? #

as? 进行安全转换,失败时返回 null:

kotlin
val obj: Any = "Hello"

val str: String? = obj as? String  // "Hello"
val num: Int? = obj as? Int        // null

5.3 使用场景 #

kotlin
fun process(obj: Any) {
    // 不安全转换
    try {
        val str = obj as String
        println(str.length)
    } catch (e: ClassCastException) {
        println("Not a String")
    }
    
    // 安全转换(推荐)
    val str = obj as? String
    println(str?.length ?: "Not a String")
}

六、字符串与数值转换 #

6.1 数值转字符串 #

kotlin
val num = 123

num.toString()           // "123"

// 格式化
String.format("%d", num)      // "123"
String.format("%04d", num)    // "0123"
String.format("%x", num)      // "7b"(十六进制)

6.2 字符串转数值 #

kotlin
// 基本转换
"123".toInt()        // 123
"123".toLong()       // 123L
"3.14".toFloat()     // 3.14f
"3.14".toDouble()    // 3.14

// 进制转换
"FF".toInt(16)       // 255
"1010".toInt(2)      // 10

// 安全转换
"abc".toIntOrNull()       // null
"123".toIntOrNull()       // 123
"FF".toIntOrNull(16)      // 255

6.3 处理转换异常 #

kotlin
fun safeToInt(str: String): Int {
    return str.toIntOrNull() ?: 0
}

// 使用
val num = safeToInt("123")
val invalid = safeToInt("abc")  // 0

七、自定义类型转换 #

7.1 定义转换函数 #

kotlin
class Person(val name: String, val age: Int) {
    fun toUser(): User {
        return User(name, age)
    }
}

class User(val name: String, val age: Int)

val person = Person("Kotlin", 10)
val user = person.toUser()

7.2 扩展函数转换 #

kotlin
fun String.toPerson(): Person {
    val parts = this.split(",")
    return Person(parts[0], parts[1].toInt())
}

val person = "Kotlin,10".toPerson()

7.3 运算符重载转换 #

kotlin
class Dollar(val amount: Double) {
    operator fun plus(other: Euro): Dollar {
        return Dollar(amount + other.amount * 1.1)
    }
}

class Euro(val amount: Double)

val dollar = Dollar(100.0)
val euro = Euro(50.0)
val total = dollar + euro

八、类型别名与转换 #

8.1 类型别名 #

kotlin
typealias UserName = String
typealias UserId = Long

fun process(name: UserName, id: UserId) {
    // 编译时类型别名会被替换为原类型
    val str: String = name
    val long: Long = id
}

8.2 类型别名不创建新类型 #

kotlin
typealias StringList = List<String>

val list1: StringList = listOf("A", "B")
val list2: List<String> = list1  // 完全相同

// 类型检查
println(list1 is List<*>)  // true
println(list1 is StringList)  // 编译错误

九、泛型类型转换 #

9.1 泛型擦除 #

kotlin
fun <T> process(list: List<T>) {
    // 运行时不知道 T 的具体类型
    // if (list is List<String>) { }  // 编译错误
}

// 使用具体化类型参数
inline fun <reified T> isType(value: Any): Boolean {
    return value is T
}

println(isType<String>("Hello"))  // true
println(isType<Int>("Hello"))     // false

9.2 星投影 #

kotlin
val list: List<*> = listOf("A", "B", "C")

if (list is List<*>) {
    println(list.size)
}

十、最佳实践 #

10.1 优先使用智能转换 #

kotlin
// 推荐
if (obj is String) {
    println(obj.length)
}

// 不推荐
if (obj is String) {
    println((obj as String).length)
}

10.2 使用安全转换 #

kotlin
// 推荐
val str = obj as? String ?: return

// 不推荐
try {
    val str = obj as String
} catch (e: ClassCastException) {
    // ...
}

10.3 尽早进行类型检查 #

kotlin
fun process(obj: Any) {
    if (obj !is String) return
    
    // 后续代码可以安全使用 String 方法
    println(obj.length)
    println(obj.uppercase())
}

10.4 使用 when 处理多种类型 #

kotlin
fun describe(obj: Any): String = when (obj) {
    is String -> "String of length ${obj.length}"
    is Int -> "Integer $obj"
    is Boolean -> if (obj) "True" else "False"
    is List<*> -> "List with ${obj.size} elements"
    else -> "Unknown type"
}

十一、总结 #

类型转换要点:

操作符/函数 用途 安全性
is / !is 类型检查 安全
as 不安全转换 可能抛异常
as? 安全转换 返回 null
toXxx() 数值转换 可能溢出
toIntOrNull() 安全数值转换 返回 null

下一步,让我们学习 字符串

最后更新:2026-03-27