Kotlin-32.空指针安全/null安全(Null Safety)

官方文档: http://kotlinlang.org/docs/reference/null-safety.html

1.可空与非空类型(Nullable types and Non-Null Types)

很多编程语言(包括Java)最常见的陷阱就是访问null引用,
在java中会导致空指针异常NullPointerException,简称NPE;
因此东尼·霍尔(Tony Hoare),图灵奖得主把Null引用称为十亿美元的错误!

Kotlin类型系统旨在消除null引用的危险,
所以在Kotlin中只有以下情况,才会导致空指针异常NullPointerException:  
    1.显式调用 throw NullPointerException();
    2.使用 !! 操作符;
    3.外部Java代码导致的;
    4.对于初始化,有些数据不一致(如构造函数中未初始化的this用于某个地方);

Kotlin类型系统能区分一个引用可null(可空引用)还是不可null(非空引用)
例如,String类型的常规变量不能为空null:
    var a: String = "abc"
    a = null //编译错误,a不能为null

    //如果要允许变量为空null,需要在类型后添加问号?标记可null:
    var b: String? = "abc"
    b = null //编译OK

    //a不能为null,所以a方法或属性,不会导致NPE(NullPointerException)
    val l = a.length

    //b可以为null,所以访问b属性是不安全的,kotlin编译器会报错
    val l = b.length //kotlin编译器会报: 变量“b”可能为null
    //要想可以访问b,在下文中有几种方法: if检查null, ?.操作符, !!操作符

2.在条件中检查null(Checking for null in conditions)

第一个选择,是显式检查b是否为null,编译器会跟踪所执行检查null:
    val l = if (b != null) b.length else -1 //编译OK
    val l = b.length //编译报错

    if (b != null && b.length > 0) {
        print("String of length ${b.length}")
    } else {
        print("Empty string")
    }

提示: 在条件中检查null,只适用于b是不可变量的情况
    (即局部变量在检查null和使用之间没有改变,
    或者成员变量val有幕后字段backing field且不可覆盖overridable),
    否则可能发生在检查之后b又变为null的情况!

3.安全调用(Safe Calls)-操作符?.

第二个选择,是使用安全调用操作符?.
如果b非空,则返回b.length,否则返回null(表达式返回类型是Int?)
    val l = b?.length //编译OK
    val l = b.length //编译报错
    
安全调用?.在链式调用中很有用,
例如,一个员工Bob可能分配给一个部门,该部门可能有一个负责人(名字):
    //以下任意变量为null空,该链式调用结果就返回null
    bob?.department?.head?.name

如果只对非空值执行操作(即忽略null),安全调用操作符?.可与let一起使用:
    val listWithNulls: List<String?> = listOf("A", null)
    for (item in listWithNulls)
        item?.let { println(it) } //输出A,(忽略null)

4.?:操作符(Elvis Operator)

除了用完整if表达式检查null,还可用Elvis操作符?:简化if表达式,
如果?:左侧表达式非空,就返回其左侧表达式,否则返回其右侧表达式
    val l = b?.length ?: -1 //当且仅当?:左侧为null时,才对右侧表达式求值
    //等价于
    val l: Int = if (b != null) b.length else -1

因为在Kotlin中throw,return都是表达式,所以也可在?:右侧,例如检查函数参数:
    fun foo(node: Node): String? {
        val parent = node.getParent() ?: return null
        val name = node.getName() ?: throw IllegalArgumentException("name expected")
        //...
    }

5.!!操作符(!! Operator)

第三个选择,是使用操作符!!,为NPE空指针异常的爱好者准备的, 让编译器不检查null
如果b变量为null,就会抛出空指针异常NullPointerException(NPE)!
例如:
    val l = b!!.length //如果b为null,会抛出空指针异常NullPointerException

6.过滤集合的可空元素-filterNotNull()

如果集合有可空类型元素的,要过滤非空元素,可用filterNotNull实现:
    val nullableList: List<Int?> = listOf(1, 2, null, 4)
    val intList: List<Int> = nullableList.filterNotNull()

简书://www.greatytc.com/p/f2da6e3eb53e
CSDN博客: http://blog.csdn.net/qq_32115439/article/details/74509791
GitHub博客:http://lioil.win/2017/07/05/Kotlin-null.html
Coding博客:http://c.lioil.win/2017/07/05/Kotlin-null.html

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

推荐阅读更多精彩内容

  • 前言 人生苦多,快来 Kotlin ,快速学习Kotlin! 什么是Kotlin? Kotlin 是种静态类型编程...
    任半生嚣狂阅读 26,166评论 9 118
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,760评论 25 707
  • 《Kotlin 极简教程》第一章 Kotlin简介 科特林岛(Котлин)是一座俄罗斯的岛屿,位于圣彼得堡以西约...
    光剑书架上的书阅读 3,059评论 8 50
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,629评论 18 139
  • 独自带婉词生活已有两个年头,一边上班一边带孩子的辛苦只有经历过的人才真正懂得,也是这时才体味出当年母亲的艰辛...
    佑妳喜乐阅读 1,731评论 0 0