美文网首页Kotlin
类型检测与类型转换:"is" 与 "as"

类型检测与类型转换:"is" 与 "as"

作者: 码农修行之路 | 来源:发表于2020-11-18 17:33 被阅读0次

"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("其它未检测的类型")
}

智能转换规则:

  • 当编译器不能保证变量在检测和使用之间不可改变时,智能转换不能用
  1. val ->局部变量 可以 局部委托属性 不可
  2. val ->属性 如果属性是private或internal 再或者该检测在声明属性的同一模块中执行 可以 open的属性或具有自定义getter的属性 不可
  3. var ->局部变量 如果变量在检测和只用之间没有修改 没有在会修改它的lambda表达式中捕获,并且不是局部委托属性 可以
  4. 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 小朱

相关文章

网友评论

    本文标题:类型检测与类型转换:"is" 与 "as"

    本文链接:https://www.haomeiwen.com/subject/ctuciktx.html