在 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 编译器会自动将对象转换为目标类型(在作用域内)。 - 适用场景 :
if
、when
表达式或局部变量等不可变场景。
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")
}
五、注意事项
-
**避免滥用
as
**显式转换可能引发运行时异常,优先使用
is
检查和智能转换。 -
**
Any
类型的隐式转换**kotlinval a: Any = 100 if (a is Int) { val b: Int = a // 无需显式转换 }
-
泛型类型的限制
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?
** :安全转换的推荐方式,避免异常。