Kotlin null的处理详解

 更新时间:2017年06月05日 11:17:08   作者:行云间  
这篇文章主要介绍了Kotlin null的处理详解的相关资料,需要的朋友可以参考下

Kotlin null的处理详解

NullPointerException,俗称NPE,不管菜鸟还是老鸟们,都是不可避免,经常遇到的一个异常,解释起来很简单,就“空指针”三个字。总是在一次不小心,而掉进这个陷阱里。Kotlin 的设计目标就是希望消除代码中 null 引用带来的危险, 也就是所谓的造成十亿美元损失的大错误.

NPE的原因

尽管Kotlin希望消除代码中的NPE,我们总是不小心,总会不小心又掉进NPE的陷阱,下面是可能NPE的原因:

  1. 明确调用 throw NullPointerException()
  2. 使用 !! 操作符
  3. 外部的 Java 代码导致这个异常
  4. 初始化过程中存在某些数据不一致 (在构造器中使用了未初始化的 this)

避免NPE

在Kotlin中,明确区分可以指向 null 的引用 (可为 null 引用) 与不可以指向null的引用 (非null引用). 比如, 一个通常的 String 类型变量不可以指向 null:

var a: String = "abc"
a = null // 编译错误

此时,你对a变量的任何调用都是安全的,因为它为非null,你可以对该引用做任何操作而不会报NPE。就算对a赋值给Null,编译器都会报错,不会让你通过。

可是,实际开发时,不可能所有的变量不会null,总会有情况,变量是null的,此时该如何设定该变量呢?要允许null值的变量, 我们可以将变量声明为可为null的字符串, 写作 String? :

var b: String? = "abc"
b = null // ok

这样,我们是解决了变量可以设置为null的问题,可NPE的这个陷阱又设上了,如果再粗心大意,NPE又来找麻烦了。

如果我们仍然需要访问这个属性, 对不对? 有以下几种方法可以实现:

在条件语句中进行null检查

通过条件语句,对变量检查是否为null,对 null 和非 null 的两种情况分别处理:

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

注:

该方案只是针对当前b的值,b的值在检查以后,如果b的值被修改仍需对此值做非null检查,也就是说每次修改b的值,都必须对b作非null验证,这也导致了代码的冗余。

安全调用

什么是安全调用?看起来有点不理解,既然是null怎么还会有安全呢?

b?.length

在Kotlin中,允许使用 “?.”操作符调用变量,其含义是如果b不是null,这个表达式将会返回b.length,否则返回 null.如果使用了”?.”,其表达式的值也应为 可为null的,比如Int?,否则编译器会报错。

bob?.department?.head?.name

安全调用在链式调用的情况下非常有用.这样的链式调用, 只要属性链中任何一个属性为 null, 整个表达式就会返回 null.

?:操作符

如果 ?: 左侧的表达式值不是null, 就会返回表达式的的值,否则, 返回右侧表达式的值.

val l = b?.length ?: -1

如果b不为null,将返回b的长度,如果为null,将返回-1

注:

只有在左侧表达式值为 null 时, 才会计算右侧表达式.

由于在 Kotlin 中 throw 和 return 都是表达式, 因此它们也可以用在 Elvis 操作符的右侧. 这种用法可以带来很大的方便, 比如, 可以用来检查函数参数值是否合法。

fun foo(node: Node): String? { 
val parent = node.getParent() ?: return null 
val name = node.getName() ?: throw IllegalArgumentException(“name expected”) 
// … 
} 

!! 操作符

对于b不为null的情况, 这个表达式将会返回这个非null值(比如, 在我们的例子中就是一个 String 类型值), 如果b是 null, 这个表达式就

会抛出一个 NPE:

val l = b!!.length()

当b为null时就抛出一个异常,你可以捕获它,而不是在不知道在某一角落里调用时,才报出异常,抓头挠腮半天,才找到NPE在哪里。

安全的类型转换

如果对象不是我们期望的目标类型, 那么通常的类型转换就会导致ClassCastException,可以选择使用安全的类型转换, 如果转换不成功, 它将会返回 null,这样避免了转换异常的抛出。

val aInt: Int? = a as? Int

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

您可能感兴趣的文章:

相关文章

  • JVM的类加载器和双亲委派模式你了解吗

    JVM的类加载器和双亲委派模式你了解吗

    这篇文章主要为大家详细介绍了JVM类加载器和双亲委派模式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • java中Map接口常用的方法解读

    java中Map接口常用的方法解读

    这篇文章主要介绍了java中Map接口常用的方法解读,Map接口是双列集合,它的每一个元素都包含一个键对象key和值对象Value,键和值对象之间存在一种对应关系,称为映射,需要的朋友可以参考下
    2024-01-01
  • 深入学习MyBatis中的参数(推荐)

    深入学习MyBatis中的参数(推荐)

    大家日常使用MyBatis经常会遇到一些异常,想要避免参数引起的错误,我们需要深入了解参数。想了解参数,我们首先看MyBatis处理参数和使用参数的全部过程。下面这篇文章主要给大家介绍了MyBatis中参数的的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-06-06
  • Java包机制及javadoc详解

    Java包机制及javadoc详解

    为了更好地组织类,Java提供了包机制,用于区别类名的命名空间,一般利用公司域名倒置作为包名,这篇文章主要介绍了Java包机制以及javadoc,需要的朋友可以参考下
    2022-10-10
  • SpringBoot2 整合FreeMarker实现页面静态化示例详解

    SpringBoot2 整合FreeMarker实现页面静态化示例详解

    这篇文章主要介绍了SpringBoot2 整合FreeMarker实现页面静态化示例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • MybatisPlus中插入数据后获取该对象主键值的实现

    MybatisPlus中插入数据后获取该对象主键值的实现

    这篇文章主要介绍了MybatisPlus中插入数据后获取该对象主键值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • Java object wait notify notifyAll代码解析

    Java object wait notify notifyAll代码解析

    这篇文章主要介绍了Java object wait notify notifyAll代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • Spring boot实现热部署的两种方式详解

    Spring boot实现热部署的两种方式详解

    这篇文章主要介绍了Spring boot实现热部署的两种方式,这两种方法分别是使用 Spring Loaded和使用spring-boot-devtools进行热部署,文中给出了详细示例代码和介绍,需要的朋友可以参考学习,下面来一起看看吧。
    2017-04-04
  • java 多线程实现在线咨询(udp)

    java 多线程实现在线咨询(udp)

    这篇文章主要介绍了java 多线程实现在线咨询(udp)的示例,帮助大家更好的理解和学习Java 网络编程的相关内容,感兴趣的朋友可以了解下
    2020-11-11
  • Java项目导出数据为 PDF 文件的操作代码

    Java项目导出数据为 PDF 文件的操作代码

    一个小需求,需要将页面上的数据导出为PDF,正常情况下这个需求需要让前端来做,但是现在上面让咱们后端来做,也没问题,这篇文章主要介绍了Java项目导出数据为 PDF 文件的操作代码,需要的朋友可以参考下
    2022-12-12

最新评论