详解Kotlin的空指针处理
作者:还不走 发布时间:2022-06-03 06:57:58
详解Kotlin的空指针处理
Kotlin的空指针处理相比于java有着极大的提高,可以说是不用担心出现NullPointerException的错误,kotlin对于对象为null的情况有严格的界定,编码的阶段就需要用代码表明引用是否可以为null,为null的情况需要强制性的判断处理。
咋看一下这些在java里面其实也有,问题是一般开发中不写也是可以的(大部分开发不会花很多时间考虑这些),等出了空指针错误再一个个打补丁。这样往往会遗漏很多空指针,后期的解决仅仅是做一个if判断,没有从根源解决问题
变量需要知道是否可以为null
第一个与java的不同,kotlin声明引用时不可以直接赋值为null
var helloA: String=null //编译器直接报错 null can not be value of a non null type string
这里插一句,kotlin的成员变量(全局变量)必须要初始化甚至是基本数据类型都要手动给一个初始值,局部变量可以不用初始化,上面的例子是成员变量的声明。
编译器直接表示hello是一个non null type你不可以直接赋一个null值。对于我们java原住民来说声明变量时如果不去赋值,编译器会默认赋null(除去基本数据类型),在kotlin这是不允许的。
类型?
当某个变量的值可以为 null 的时候,必须在声明处的类型后添加 ? 来标识该引用可为空。
这是官方文档的说明,也就是说上面的变量声明只需要在String类型后面加一个?就可以解决这个错误。
var helloB : String? = null
如果不用?也可以直接初始化来解决问题
var helloA : String = "hello"
String和String?
helloA 和 helloB2个变量的类型分别为String和String?,这2种类型的区别在于引用时是否空安全,String?代表可能为空,引用不安全,String代表不会为空,引用安全。比如调用一下helloB的方法
可以看到有些方法是灰的代表不能直接调用,有些是白的代表可以直接调用,为什么可以直接调用后面再讲
helloB.length //Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
这里的错误解释简单的理解就是helloB是一个可能为空的类型(String?),对于可空类型你必须做判空的处理才能调用方法。有没有爱上kotlin? wtf太厉害了
如何做判空处理
最简单的方法就是使用?.来调用方法。这个符号的意义是,当helloB不为空调用.length方法,返回Int值,如果helloB为空则返回null。
helloB?.length
注意这里的返回值类型为Int? 依然是可以为空的类型
不推荐的写法!!这个操作符可以说是为了空指针错误爱好者准备的,使用了!!操作符代表你不关心变量的空判断可以报出NullPointerException,又或者你有绝对的自信这里肯定不为空,可以放心的调用,可以说!!放弃了判空的检查
helloB!!.length
Elvis 操作符?:
回到?.的调用上来,这个调用方式存在一个让人不安的处理,就是在变量为null的情况下,会直接返回null,这样空指针的隐患还在。
var l : Int = helloB?.length //报错类型不匹配 Int? 和 Int
修正的话需要通过if判断来进行判空处理
var l: Int = if (helloB?.length != null) helloB.length else -1
这种写法可以简化成Elvis 操作符?:
var le: Int = helloB?.length ?: 0
当?:左边非空返回左边的值,左边为空则返回右边的值
最后前文提到的当helloB为空时有些方法仍然可以调用比如equals方法
helloB.equals(helloA)
即使helloB为可空类型依然可以调用equals方法,但是这里的equals方法并不是String.java的equals方法,而是StringJvm.kt中的equals方法
public fun String?.equals(other: String?, ignoreCase: Boolean = false): Boolean {
if (this === null)
return other === null
return if (!ignoreCase)
(this as java.lang.String).equals(other)
else
(this as java.lang.String).equalsIgnoreCase(other)
}
关键代码
this===null
return other === null
这个方法对变量本身为null的情况已经做了判断,同时方法写成了String?.equals可以让String?类型的对象直接调用这个equals方法
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!


猜你喜欢
- 在android开发中,经常会遇到一个view需要它能够支持滑动的需求。下面通过本篇文章给大家介绍android view移动的六种方法。l
- Java 分割字符串java.lang.String 的 split() 方法, JDK 1.4 or laterpublic
- 在看别人的关于CopyOnWriteArrayList 这个类的时候,看到有人提出了关于:数组拷贝的方法Arrays.copyOf() 的问
- 贪婪量词:先看整个字符串是不是一个匹配。如果没有发现匹配,它去掉最后字符串中的最后一个字符,并再次尝试。如果还是没有发现匹配,那么 
- 1, 泛型接口的协变如果泛型类型用out关键字标注,泛型接口就是协变的。这也意味着返回类型只能是T。泛型接口的抗变如果泛型类型用in关键字标
- public class BeanDefinitionHolder implements BeanMetadataElement { &nb
- 类是使用关键字 class 声明的,如下面的示例所示:访问修饰符 class 类名 { //类成员: // Methods, prope
- Android package属性、package name和Application ID三者的联系及区别package属性:在Androi
- 概述:Flutter中常用的滑动布局 ScrollView 有 SingleChildScrollView、NestedScrollView
- 有段时间没有写博客了,也在努力的从传统单机开发向分布式系统过度,所以再次做一些笔记,以方便日后查看。直接进入正题吧,今天记录spring-b
- 程序目的从java字节码层理解,为何i = i++后,结果是+1之前的数值。而i=++i后,结果是+1之后的值。关键指令iload_<
- 我先说说这两种的方式的不同之处吧 第一种: 在调动成功之后 不会让你指纹解锁 而是调转到当初你设置指纹解锁时的 手势解锁页面 第二种: 在调
- 前言二进制文件读写两个重要的函数 , fread 和 fwrite , fread 用于读取文件 , fwrite 用于写出文件 ;frea
- mongodb是最早热门非关系数据库的之一,使用也比较普遍,一般会用做离线数据分析来使用,放到内网的居多。由于很多公司使用了云服务,服务器默
- 在 C# 中没有提供方法用来对 MessageBox 进行定位,但是通过 C++ 你可以查找窗口并移动它们,本文讲述如何在 C#
- 网上找了一些获取客户端IP的方法,但本地测试时,返回的是IPv6的表示方法"::1":Host文件里面:# &
- 本文所述为基于C#实现的端口扫描器代码,代码内包括了窗体和逻辑处理两部分代码。在代码中,创建TcpClient对象,把TcpClient用于
- 并行和并发并行:多个CPU实例或是多台机器同时执行一段处理逻辑,是真正的同时。并发:一个CPU或一台机器,通过CPU调度算法,让用户看上去同
- 简介本文用示例介绍java的Period的用法。Duration和Period说明Duration类通过秒和纳秒相结合来描述一个时间量,最高
- 1 pom.xml文件注:热部署功能spring-boot-1.3开始有的<!--添加依赖--><dependency&g