Kotlin学习系列——智能转换
官方文档: http://kotlinlang.org/docs/reference/typecasts.html
1.is和!is操作符(Operators)
在运行时,可用is或!is操作符来检查对象类型是否符合要求:
if (obj is String) {
print(obj.length)
}
if (obj !is String) { //等价于 !(obj is String)
print("Not a String")
}else {
print(obj.length)
}
1
2
3
4
5
6
7
8
9
10
2.智能转换(Smart Casts)
与java不同,Kotlin一般不需要显式转换对象类型,
因为对于不可变的值,编译器能跟踪is检查类型,在需要时会自动插入类型转换代码(安全):
fun demo(x: Any) {
if (x is String) {
print(x.length) //编译器自动把x转换为String类型
}
}
1.智能转换的例子
kotlin编译器足够聪明,能识别反向检查类型!is操作符,会自动插入类型转换代码:
if (x !is String) return
print(x.length) //编译器自动把x转换为String类型:
// ||右侧, x自动转换为String类型
if (x !is String || x.length == 0) return
// &&右侧, x自动转换为String类型
if (x is String && x.length > 0) {
print(x.length) // x 自动转换为字符串
}
//智能转换(smart casts)也用于when表达式和while循环
when (x) {
is Int -> print(x + 1)
is String -> print(x.length + 1)
is IntArray -> print(x.sum())
}
2.智能转换的适用条件
如果不能保证变量在类型检查is/!is操作符和变量使用之间不可改变时,智能转换不能用!
智能转换的适用条件/规则:
val局部变量-总是适用!
val属性-适用于private或internal,或者类型检查is/!is在声明属性的同一模块中执行;
不适用于open的属性,或者具有自定义getter的属性!
var局部变量—适用于变量在类型检查和使用之间没有修改,且不在修改它的lambda中捕获!
var属性-不适用(因为该变量可随时被修改)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
3.不安全转换-操作符as
如果类型不可能转换,转换操作符会抛出异常,称为不安全转换!
Kotlin不安全转换就是中缀操作符as,例如:
val y = null
//kotlin类型默认不能为空(null),as会抛出异常TypeCastException
val x: String = y as String
//必须在转换右边添加?,表示可空(null)类型:
val x: String? = y as String?
1
2
3
4
5
6
7
8
4.安全(可空)转换-操作符as?
为避免抛出异常,可用安全转换操作符as?,在失败时返回null
val x: String? = y as? String
尽管as?右边是一个非空类型String,但是as?转换失败时返回可空(null)
说白了就是,as?函数参数String不能为null,但是as?函数的返回值可以是null
1
2
3
4
5
5.类型转换异常
我们都知道在 Java 中如果强制类型转换出错,那么程序就会崩溃报错类型转化异常,那么如果我们写错了会怎么样呢?将上面的代码故意改错,定义 parent 为 Parent 类型的,代码如下:
//创建父类 Parent
open class Parent
//创建子类 Child
class Child:Parent(){
val name:String = "张三"
}
fun main(args: Array<String>) {
//智能强制类型转化
val parent:Parent = Parent()
if (parent is Child){
println(parent.name)
}
}
运行之后发现,程序没有抛出异常,但是也什么都没有打印;可以看出来在 Kotlin 中,即使我们写错了,也不会导致程序崩溃。
6. Kotlin 智能类型转换总结
写法:先加判断再写逻辑,如: if (parent is Child) println(parent.name)
优点:不会抛出类型转换异常
还没有评论,来说两句吧...