ZetCode

Kotlin 关键字 'as'

最后修改于 2025 年 4 月 19 日

Kotlin 的类型转换系统提供了安全和不安全的方式在类型之间进行转换。关键字 as 是类型转换操作的核心。本教程将通过实际示例深入探讨 as 关键字。

基本定义

Kotlin 中的 as 关键字用于类型转换。它有两种形式:不安全转换 (as) 和安全转换 (as?)。不安全转换在转换失败时抛出异常,而安全转换则返回 null。

使用 as 的不安全转换

基本的 as 运算符执行不安全转换。如果转换失败,它会抛出 ClassCastException。当您确定类型时使用此方法。

UnsafeCast.kt
package com.zetcode

fun main() {

    val obj: Any = "Hello Kotlin"
    val str: String = obj as String
    
    println(str.length) // Output: 12
}

在这里,我们使用 asAny 类型转换为 String。转换成功,因为底层对象是 String。然后代码打印字符串的长度。

使用 as? 的安全转换

当转换失败时,安全转换运算符 as? 返回 null 而不是抛出异常。对于类型不确定的情况,这更安全。

SafeCast.kt
package com.zetcode

fun main() {

    val obj: Any = 123
    val str: String? = obj as? String
    
    println(str) // Output: null
}

在这里,我们尝试使用 as? 将 Int 转换为 String。由于此转换是不可能的,因此结果是 null 而不是异常。这在处理未知数据类型时很有用。

数值类型之间的转换

Kotlin 要求在数值类型之间进行显式转换。关键字 as 可以用于此目的,但仅当类型兼容时。

NumericCast.kt
package com.zetcode

fun main() {

    val x: Int = 100
    val y: Long = x.toLong() // Preferred way
    val z: Long = x as Long // Compile error
    
    println(y)
}

此示例表明,不允许使用 as 在数值类型之间直接转换。相反,请使用像 toLong 这样的转换函数。注释掉的行将导致编译错误。

继承层次结构中的转换

当在继承层次结构内进行转换时,as 关键字效果很好。如果对象实际上是子类型,则可以将父类转换为子类。

InheritanceCast.kt
package com.zetcode

open class Animal
class Dog : Animal() {
    fun bark() = println("Woof!")
}

fun main() {

    val animal: Animal = Dog()
    val dog: Dog = animal as Dog
    dog.bark() // Output: Woof!
}

在这里,我们成功地将 Animal 转换为 Dog,因为底层对象实际上是一个 Dog。转换后,我们可以调用 Dog 独有的方法,例如 bark()。

智能转换

Kotlin 的智能转换会在类型检查后自动处理转换。虽然不直接使用 as,但它们与类型转换的概念相关。

SmartCast.kt
package com.zetcode

fun printLength(obj: Any) {
    if (obj is String) {
        println(obj.length) // Smart cast to String
    }
}

fun main() {

    printLength("Kotlin") // Output: 6
    printLength(123) // No output
}

在检查 obj is String 之后,Kotlin 会自动将 obj 转换为 if 块内的 String。这消除了在许多情况下显式使用 as 转换的需要。

泛型和转换

使用泛型时,您可能需要转换为泛型类型。as 关键字可以在这里使用,但要注意类型安全。

GenericCast.kt
package com.zetcode

fun <T> castToType(obj: Any): T? {
    return obj as? T
}

fun main() {

    val result: String? = castToType("Hello")
    println(result) // Output: Hello
    
    val failed: Int? = castToType("Not a number")
    println(failed) // Output: null
}

此泛型函数尝试使用安全转换将任何对象转换为类型 T。第一个调用成功,而第二个调用则优雅地失败,返回 null 而不是抛出异常。

具体化类型参数

通过在内联函数中使用具体化类型参数,您可以在运行时访问实际类型并执行更安全的转换。

ReifiedCast.kt
package com.zetcode

inline fun <reified T> safeCast(obj: Any): T? {
    return obj as? T
}

fun main() {

    val s: String? = safeCast("Kotlin")
    val i: Int? = safeCast(123)
    
    println(s) // Output: Kotlin
    println(i) // Output: 123
}

具体化的类型参数保留了运行时的类型信息,使安全转换操作更具类型安全性。这在需要执行类型检查的泛型函数中特别有用。

类型转换的最佳实践

来源

Kotlin 类型转换文档

本教程深入探讨了 Kotlin 的 as 关键字,展示了安全和不安全转换操作。我们探讨了各种场景,包括继承、泛型和智能转换。正确使用类型转换可以使您的代码更灵活,同时保持类型安全。

作者

我的名字是 Jan Bodnar,我是一位充满激情的程序员,拥有多年的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我已经撰写了 1400 多篇文章和 8 本电子书。我拥有超过八年的编程教学经验。

列出 所有 Kotlin 教程