美文网首页Kotlin
空安全之可空、非空类型及其操作符使用

空安全之可空、非空类型及其操作符使用

作者: 码农修行之路 | 来源:发表于2020-11-16 16:59 被阅读0次
    亲自码一遍 可空类型和非空类型 以及 操作符使用规则及其注意点
    • 引入:在Java中 异常 NullPointerException 简称 NPE 空指针异常 也是最常见的异常之一
      // 在KT中,出现NPE现象的原因无非就下面几种:
      // (1). 代码中显示地调用了 throw NullPointerException
      // (2). Java互操作
      // 1. 外部Java代码导致
      // 2. 企图访问平台类型的null引用的成员
      // 3. 用于具有错误可空性的Java互操作,例如List<String> 中添加 null 需要添加可空类型 List<String?>俩处理
      // (3). 使用 !! 操作符
      // (4). 对于初始化时,有些数据可能不一致:
      // 1. 如果一个未初始化的this 用在构造函数的某个地方
      // 2. 超类的构造函数中调用一个开放成员,该成员在派生类中实现使用了为初始化的状态
    可空类型和非空类型
    fun main() {
        // KT 中类型系统区分一个引用是否可容纳null还是不能容纳,例子展示
        // 非空类型只能赋值为非空
        var str1: String;// 使用之前必须赋值,否则编译时异常
        1. println("$str1") // Variable 'str1' must be initialized
        // var str2: String = null // 非空类型不能赋值为不为空 否则提示错误:Null can not be a value of a non-null type String
        var str3: String = "hgz";
        // 如过我们就是要访问可空类型的str4的属性,可以添加可空类型 操作符 ? 就不会编译时异常 返回为null
        var str4: String? = null
        println("$str4") // 返回结果 null 不会报PNE
        // 如果调用可空类型对象的一些函数或者属性 正常调用就会提示下面错误
        // 可空函数的引用需要使用 空安全调用符 或者 非空断言 来修饰 才可以使用 再或者使用显示检测str4是否为null
        // var len = str4.length // 错误提示 Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
        var len1 = str4?.length
        // 或
        //var len2 = str4!!.length// 如果str4为null 运行时异常 NPE java.lang.NullPointerException
        // 或
        var len3 = if (str4 != null) str4.length else -1
        // 简写为
        var len4 = str4?.length ?: -1
        println(len1)
        //println(len2)
        println(len3)
        println(len4)
        //str4 = "hgz"
        // 空安全调用符 ?. 在链式调用中是很有用的 比如
        // 如果链式调用中的任何一个属性(环节)为空,这个链式调用就会返回null
        str4?.length?.let { // 对非空值进行操作
            println("居然有数据")
        }.toString();
        println(str4)
        str4 = "hgz"
        str4?.length.toString();
        println(str4)
    
        // 对可空数据类型的数据进行操作 比如在可空的集合中,对集合中非空值的数据进行操作,那么安全调用符可以与let一起使用
        var listWithNulls: List<String?> = listOf("熳熳", null, "杨杨", "莹莹", null)
        listWithNulls.forEach {
            it?.let {
                // 只操作非空值
                println(it)
            }
        }
        // 打印返回值:熳熳 杨杨 莹莹
    
        // 还有一点注意:安全调用符也可以出现在赋值的左侧 personal?.user?.name = "小黄"
    
        // Elvis操作符 相当于java中的三目运算符
        // 操作符:?:
        var name: String? = null// 可空类型
        //var name: String? = "小黄"// 非空类型
        var nameLen = name?.length ?: -1
        println(nameLen)
        // 上述可空的引用name,如果想让它为null的时候返回某一个非空的值(-1),不为空时返回自身某一个属性值(length)
        // 操作符理解 ?: 左侧的表达式非空 就返回 ?: 左侧的表达式值 ,否则返回 ?: 右侧的表达式值
        // 注意:只有 ?: 操作符 左侧表达式为空的时 才会对右侧的表达式求值
    
    
        // 非空断言 操作符 !!
        // 非空断言操作符 将任何值转换为非空类型 如若该值为空 就会抛出PNE异常
        var sex: String? = null
        try {
            println(sex!!) // 异常 java.lang.NullPointerException
        } catch (e: NullPointerException) {
            // 需要自己手动处理异常
            sex = "男"
            println("默认值:$sex")
        }
    
        // 安全类型转换
        val a: String = "1"
        // 如若对象不是目标,类型转换异常抛出
        // val aInt:Int = a as Int // 错误提示 java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
        // 如若想避免异常,可以使用安全的类型转换 as?
        val aInt: Int? = a as? Int // 返回值为 null
        println(aInt)
    
        // 可空类型的集合
        var listStr: List<String?> = listOf("蛋蛋", "二蛋", null, "小花", "小芳", null, "小智")
        // 怎样获取上述可空集合的非空值并以集合类型返回 可以通过 filterNotNull() 函数实现
        var nonNullList: List<String> = listStr.filterNotNull();
        nonNullList.forEach { i ->
            println(i)
        }
    }
    

    总结:

    1. 非空类型只能赋值为非空
    2. 变量使用之前必须赋值,否则编译时异常
    3. 如果变量赋值为空 需要添加可空操作符 ?
    4. 如果调用可空类型对象的一些函数或者属性 正常调用就会提示下面错误
      错误提示 Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
    5. 可空函数的引用需要使用 空安全调用符 或者 非空断言 来修饰 才可以使用 再或者使用显示检测str4是否为null
    6. 空安全调用符 ?. 在链式调用中是很有用的,如果链式调用中的任何一个属性(环节)为空,这个链式调用就会返回null
    7. 对可空数据类型的数据进行操作 比如在可空的集合中,对集合中非空值的数据进行操作,那么安全调用符可以与let一起使用
    8. 安全调用符也可以出现在赋值的左侧 personal?.user?.name = "小黄"
    9. Elvis操作符 ?: 相当于java中的三目运算符
      操作符理解 ?: 左侧的表达式非空 就返回 ?: 左侧的表达式值 ,否则返回 ?: 右侧的表达式值
      只有 ?: 操作符 左侧表达式为空的时 才会对右侧的表达式求值
    10. 非空断言操作符 将任何值转换为非空类型 如若该值为空 就会抛出PNE异常 异常需要自己手动处理
    11. 安全类型转换 如若对象不是目标类型,类型转换异常抛出 ClassCastException
      如若想避免异常,可以使用安全的类型转换 as?
    12. 可空类型的集合 获取非空值的数据并且以集合形式返回 可以通过 filterNotNull() 函数实现

    谢谢亲们的关注支持 记得点赞哦!

    相关文章

      网友评论

        本文标题:空安全之可空、非空类型及其操作符使用

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