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

亲自码一遍 可空类型和非空类型 以及 操作符使用规则及其注意点
  • 引入:在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() 函数实现

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,313评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,369评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,916评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,333评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,425评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,481评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,491评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,268评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,719评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,004评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,179评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,832评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,510评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,153评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,402评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,045评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,071评论 2 352

推荐阅读更多精彩内容