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

来源:互联网 发布:知乎收藏夹 编辑:程序博客网 时间:2024/05/18 03:36

官方文档: 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()

简书:http://www.jianshu.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

原创粉丝点击