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 分钟前
DrawerLayout 滑动冲突
android
玲小珑1 小时前
Auto.js 入门指南(六)多线程与异步操作
android·前端
用户2018792831673 小时前
通俗易懂理解Java注解
android
用户2018792831673 小时前
通俗易懂理解泛型
android
linversion3 小时前
如何手动上传Android混淆映射文件Mapping.txt到Firebase
android
慕晨3 小时前
RecyclerView + SnapHelper 滚动差异问题
android
玲小珑3 小时前
Auto.js 入门指南(三)第一个 Auto.js 脚本
android·前端
aningxiaoxixi4 小时前
Android Studio 之基础代码解析
android·ide·android studio
A-花开堪折4 小时前
Android7 Input(十)View 处理Input事件pipeline
android·嵌入式硬件
Shujie_L5 小时前
Android基础回顾】六:安卓显示机制Surface 、 SurfaceFlinger、Choreographer
android