"is" 与 "as"
"is" 操作符 代表对象是否是该指定类型
"!is" 操作符 代表对象是否不是该指定的类型
例如:
fun main() {
val str: Any = "小黄";
// 变量str是Any类型 通过is智能转换为String
if (str is String) {
println("是String子类型")
} else {
println("非String子类型")
}
// 或者
if (str !is Int) {
println("不是Int类型")
} else {
println("是Int类型")
}
}
- 相当于Java中关键字 instanceof
if(str instanceof String ) {
Log.i("test"," 是其子类 ");
}
智能转换 应用于while循环 when表达式:
when (str) {
is String -> println("是字符串类型")
is Int -> println("是Int类型")
is IntArray -> println("是Int数组类型")
else -> println("其它未检测的类型")
}
智能转换规则:
- 当编译器不能保证变量在检测和使用之间不可改变时,智能转换不能用
- val ->局部变量 可以 局部委托属性 不可
- val ->属性 如果属性是private或internal 再或者该检测在声明属性的同一模块中执行 可以 open的属性或具有自定义getter的属性 不可
- var ->局部变量 如果变量在检测和只用之间没有修改 没有在会修改它的lambda表达式中捕获,并且不是局部委托属性 可以
- var ->属性 绝不可能(因为该变量随时可以被其它代码修改)
"不安全的"转换操作符
- 如果遇到转换不可能的,转换操作符会抛出异常 因此称之为不安全的
fun main() {
val y: String? = null;
// 异常 java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String
val x: String = y as String
}
- null 不能转换为 String类型 String类型不是可空类型 上述示例标明 y 为空 y as String 就会抛出NPE,为了让代码用于可空值,可以在类型转换的右侧使用可空类型 ? 例如:
fun main() {
val y: String? = null;
// 异常 java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String
val x: String? = y as String?
}
"安全的"(可空)转换操作符
fun main() {
//val y1: Int? = null;
val y1: Int = 0;
// java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
//val x1: String = y1 as String
// 使用安全转换操作符 可以处理类型转换异常问题
val x1: String? = y1 as? String
println(x1)
}
- 尽管事实上 as? 的右边是一个非空类型的 String 但是其转换的结果是可空的 也可以在类型转换不同时 返回 null
类型擦除
KT在编译的时确保涉及泛型操作的类型安全性,而在运行时,泛型类型的实例并未带有关于它们实际类型参数的信息 例如:List<Foo> 会被擦除为 List<*> 通常,在运行时无法检测一个实例是否属于带有某个类型参数的泛型类型
为此 编译器会禁止由于类型擦除而无法执行的is检测 例如 ints is List<Int> 或者 list is T(类型参数) 当然,可以对一个实例检测星投影的类型:
fun main() {
val list = listOf(22, 33, 44, 55)
if (list is List<*>) {
list.forEach {
println(it)
}
}
val body1 = Body("小黄")
val body2 = Body("小杨")
val body3 = Body("小王")
var listBody = listOf(body1, body2, body3)
if (listBody is List<*>) {
listBody.forEach {
println(it)
}
}
}
data class Body(val name: String)
- 当已经让一个实例的类型参数(在编译期)静态检测 就可以对涉及非泛型部分做is检测或者类型转换(as)
fun main() {
val list1 = arrayListOf("小黄", "小李", "小朱")
handlerStrings(list1);
val listA = arrList as List<String>
listA.forEachIndexed { index, value ->
println(" list $index $value ")
}
}
fun handlerStrings(arrList: ArrayList<String>) {
if (arrList is List<String>) {
// arrList 会智能转换为 List<String>
arrList.forEach {
println(it)
}
}
}
执行结果:
arrayList 0 小黄
arrayList 1 小李
arrayList 2 小朱
list 0 小黄
list 1 小李
list 2 小朱
网友评论