空指针安全 3个月前

编程语言
264
空指针安全

我们写代码的时候知道,在Java中NPE(NullPointerExceptions)是一件成程序员几近崩溃的事情。很多时候,虽然费尽体力脑力,仍然防不胜防。

以前,当我们不确定一个DTO类中的字段是否已初始化时,可以使用@Nullable和@NotNull注解来声明,但功能很有限。

现在好了,Kotlin在编译器级别,把你之前在Java中需要写的null check代码完成了。

但是,当我们的代码

  • 显式调用 throw NullPointerException()
  • 使用了 !! 操作符
  • 调用的外部 Java 代码有NPE
  • 对于初始化,有一些数据不一致(如一个未初始化的 this 用于构造函数的某个地方)

也可能会发生NPE。

在Kotlin中null等同于空指针。我们来通过代码来看一下null的有趣的特性:

首先,一个非空引用不能直接赋值为null :

>>> var a="abc"
>>> a=null
error: null can not be a value of a non-null type String
a=null
  ^

>>> var one=1
>>> one=null
error: null can not be a value of a non-null type Int
one=null
    ^

>>> var arrayInts = intArrayOf(1,2,3)
>>> arrayInts=null
error: null can not be a value of a non-null type IntArray
arrayInts=null
          ^

这样,我们就可以放心地调用 a 的方法或者访问它的属性,不会导致 NPE

>>> val a="abc"
>>> a.length
3

如果要允许为空,我们可以在变量的类型后面加个问号?声明一个变量为可空的:

>>> var a:String?="abc"
>>> a=null
>>> var one:Int?=1
>>> one=null
>>> var arrayInts:IntArray?=intArrayOf(1,2,3)
>>> arrayInts=null
>>> arrayInts
null

如果我们声明了一个可空String?类型变量na ,然后直接调用length属性,这将是不安全的。编译器会直接报错:

>>> var na:String?="abc"
>>> na=null
>>> na.length
error: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
na.length
  ^

我们使用安全调用?. 和 非空断言调用 !!.

>>> na?.length
null
>>> na!!.length
kotlin.KotlinNullPointerException

我们可以看出,代码返回了nullkotlin.KotlinNullPointerException

安全调用在链式调用中很有用。在调用链中如果任意一个属性(环节)为空,这个链式调用就会安全返回 null。

如果要只对非空值执行某个操作,安全调用操作符可以与 let (以调用者的值作为参数来执行指定的函数块,并返回其结果)一起使用:

>>> val listWithNulls: List<String?> = listOf("A", "B",null)
>>> listWithNulls
[A, B, null]

>>> listWithNulls.forEach{
... it?.let{println(it)}
... }
A
B

参考资料

1.wiki: operator

image
EchoEcho官方
无论前方如何,请不要后悔与我相遇。
1377
发布数
439
关注者
2223678
累计阅读

热门教程文档

CSS
33小节
Redis
14小节
Gin
17小节
Flutter
105小节
C
14小节