Kotlin 的类型转换

在 Kotlin 中,类型转换和类型检查是处理对象类型安全的核心操作,主要通过 ‌**is‌(类型检查)和 ‌ as**‌(类型转换)两个操作符实现。以下是详细规则和示例:


一、类型检查操作符 is

作用 ‌:检查对象是否属于某个类型,返回 Boolean 值。

1. 基本用法

kotlin 复制代码
fun printLength(obj: Any) {
    if (obj is String) {
        // 此处 obj 自动智能转换为 String 类型
        println(obj.length)
    }
}

2. 智能转换(Smart Cast)

  • 当通过 is 检查类型后,Kotlin 编译器会自动将对象转换为目标类型(在作用域内)。
  • 适用场景 ‌:ifwhen 表达式或局部变量等不可变场景。
scss 复制代码
when (obj) {
    is Int -> println(obj + 1) // 自动转换为 Int
    is String -> println(obj.uppercase()) // 自动转换为 String
}

3. 反向检查 !is

kotlin 复制代码
if (obj !is Int) {
    println("Not an Int")
}

二、类型转换操作符 as

作用 ‌:将对象显式转换为目标类型。若类型不匹配,抛出 ClassCastException

1. 基本用法

rust 复制代码
val obj: Any = "Hello"
val str: String = obj as String // 显式转换为 String

显示转换 具有记忆功能,也就是智能类型转换,如下面案例:

kotlin 复制代码
open class Person3(private val name:String){
    fun showPersonName() = "父类的姓名是:$name"
    open fun printlnName() = println("$name")
    fun methodPerson() = println("我是父类的方法...") // 父类独有的函数
}

class Student3(private val subName:String):Person3(subName){
    fun showName() = "子类 的姓名是【${subName}】"
    override fun printlnName() = println(showName())
}

fun main(){
  val p:Person3  = Student3("张三")
    p.methodPerson()
    p.methodPerson()
    p.methodPerson()
}

运行结果如下

2. 安全转换 as?

  • 若转换失败,返回 null 而不是抛出异常。
  • 适用场景‌:不确定类型时,避免程序崩溃。
kotlin 复制代码
val num: Int? = "123" as? Int // num = null

三、关键区别与使用场景

操作符 行为 返回值 适用场景
is 检查类型是否匹配 Boolean 类型检查 + 智能转换
as 强制转换(可能抛出异常) 目标类型 确定类型匹配时的显式转换
as? 安全转换(失败返回 null 目标类型? 不确定类型时的安全转换

四、示例场景

1. 配合 when 使用智能转换

kotlin 复制代码
fun describe(obj: Any) = when (obj) {
    is Int -> "Int: $obj"
    is String -> "String: ${obj.length} chars"
    else -> "Unknown type"
}

2. 安全转换处理潜在风险

arduino 复制代码
val unknown: Any = 123
val text: String? = unknown as? String // 转换失败返回 null
println(text?.length ?: "Not a String")

3. 显式转换的异常处理

kotlin 复制代码
try {
    val num: Int = "ABC" as Int // 抛出 ClassCastException
} catch (e: ClassCastException) {
    println("Conversion failed")
}

五、注意事项

  1. ‌**避免滥用 as**‌

    显式转换可能引发运行时异常,优先使用 is 检查和智能转换。

  2. ‌**Any 类型的隐式转换**‌

    kotlin 复制代码
    val a: Any = 100
    if (a is Int) {
        val b: Int = a // 无需显式转换
    }
  3. 泛型类型的限制

    Kotlin 的泛型在运行时会被擦除,因此无法直接检查泛型类型:

    swift 复制代码
    // 以下代码无法通过编译
    if (list is List<String>) { ... }

案例

kotlin 复制代码
open class Person2(private val name: String) {

    fun showName() = "父类 的姓名是【$name】"
    // KT所有的函数,默认是final修饰的,不能被重写,和Java相反
    open fun myPrintln() = println(showName())
}

class Student2(private val subName: String) : Person2(subName) {
    fun showName2() = "子类 的姓名是【${subName}】"
    override fun myPrintln() = println(showName2())

}

// 1.普通运行子类输出
// 2.is Person Student File
// 3.is + as 转换
fun main() {
    val p: Person2 = Student2("王五")
    p.myPrintln()

    println(p is Person2)
    println(p is Student2)
    println(p is File)

    // is + as = 一般是配合一起使用
    if (p is Student2) {
        (p as Student2).myPrintln()
    }

    if (p is Person2) {
        // (p as Person2).myPrintln() // 因为子类重写了父类
        println((p as Person2).showName())
    }

六、总结

  • ‌**is**‌:用于安全类型检查,并触发智能转换。
  • ‌**as**‌:在确定类型时强制转换(风险较高)。
  • ‌**as?** ‌:安全转换的推荐方式,避免异常。
相关推荐
小蜜蜂嗡嗡37 分钟前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi0043 分钟前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体
zhangphil2 小时前
Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值
android
你过来啊你3 小时前
Android View的绘制原理详解
android
移动开发者1号5 小时前
使用 Android App Bundle 极致压缩应用体积
android·kotlin
移动开发者1号5 小时前
构建高可用线上性能监控体系:从原理到实战
android·kotlin
ii_best10 小时前
按键精灵支持安卓14、15系统,兼容64位环境开发辅助工具
android
美狐美颜sdk11 小时前
跨平台直播美颜SDK集成实录:Android/iOS如何适配贴纸功能
android·人工智能·ios·架构·音视频·美颜sdk·第三方美颜sdk
恋猫de小郭15 小时前
Meta 宣布加入 Kotlin 基金会,将为 Kotlin 和 Android 生态提供全新支持
android·开发语言·ios·kotlin
aqi0016 小时前
FFmpeg开发笔记(七十七)Android的开源音视频剪辑框架RxFFmpeg
android·ffmpeg·音视频·流媒体