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?** ‌:安全转换的推荐方式,避免异常。
相关推荐
安卓理事人2 小时前
安卓LinkedBlockingQueue消息队列
android
万能的小裴同学3 小时前
Android M3U8视频播放器
android·音视频
q***57744 小时前
MySql的慢查询(慢日志)
android·mysql·adb
JavaNoober4 小时前
Android 前台服务 "Bad Notification" 崩溃机制分析文档
android
城东米粉儿5 小时前
关于ObjectAnimator
android
zhangphil6 小时前
Android渲染线程Render Thread的RenderNode与DisplayList,引用Bitmap及Open GL纹理上传GPU
android
火柴就是我7 小时前
从头写一个自己的app
android·前端·flutter
lichong9518 小时前
XLog debug 开启打印日志,release 关闭打印日志
android·java·前端
用户69371750013848 小时前
14.Kotlin 类:类的形态(一):抽象类 (Abstract Class)
android·后端·kotlin
火柴就是我9 小时前
NekoBoxForAndroid 编译libcore.aar
android