Kotlin学习系列(四)Kotlin数据类型-part2(可空类型)

本系列内容均来自《Kotlin从小白到大牛》一书,感谢作者关东升老师。
Kotlin语言与Swift语言类似, 默认情况下所有的数据类型都是非空类型( NonNull) , 声明的变量都是不能接收空值( null) 的。 这一点与Java和Objective-C等语言有很大的不同。

1 可空类型概念

Kotlin的非空类型设计能够有些防止空指针异常( NullPointerException) , 空指针异常引起的原因是试图调用一个空对象的函数或属性, 则抛出空指针异常。 在Kotlin中可以将一个对象的声明为非空类型, 那么它就永远不会接收空值, 否则会发生编译错误。
示例代码如下:

var n: Int = 10
n = null //发生编译错误

上述代码n = null会发生编译错误, 因为Int是非空类型, 它所声明的变量n不能接收空值。 但有些场景确实没有数据, 例如查询数据库记录时, 没有查询出符合条件的数据是很正常的事情。 为此, Kotlin为每一种非空类型提供对应的可空类型( Nullable) , 就是在非空类型后面加上问号( ?) 表示可空类型。 修改上面示例代码:

var n: Int? = 10
n = null //可以接收空值( null)

Int?是可空类型, 它所声明的变量n可以接收空值。 可空类型在具体使用时会有一些限制:

  • 不能直接调用可空类型对象的函数或属性。
  • 不能把可空类型数据赋值给非空类型变量。
  • 不能把可空类型数据传递给非空类型参数的函数。

为了“突破”这些限制, Kotlin提供了如下运算符:

  • 安全调用运算符: ?.
  • 安全转换运算符: as?
  • Elvis运算符: ?:
  • 非空断言: !!

此外, 还一个let函数帮助处理可空类型数据,本文重点介绍安全调用运算符( ?.) 、Elvis运算符( ?:) 和非空断言( !!) 。

2 使用安全调用运算符( ?.)

可空类型变量使用安全调用运算符( ?.) 可以调用非空类型的函数或属性。 安全调用运算符( ?.) 会判断可空类型变量是否为空, 如果是则不会调用函数或属性, 直接返回空值;否则返回调用结果
示例代码如下:

//声明除法运算函数
fun divide(n1: Int, n2: Int): Double? {
    130
    if (n2 == 0) {//判断分母是否为0
        return null
    }
    return n1.toDouble() / n2
}

fun main(args: Array<String>) {
    val divNumber1 = divide(100, 0) ①
    val result1 = divNumber1?.plus(100)//divNumber1+100, 结果null ②
    println(result1)
    val divNumber2 = divide(100, 10) ③
    val result2 = divNumber2?.plus(100)//divNumber2+100, 结果110.0 ④
    println(result2)
}

上述代码自定义了divide函数进行除法运算, 当参数n2为0的情况下, 函数返回空值, 所以函数返回类型必须是Double的可空类型, 即Double?。

代码第①行和第③行都调用divide函数, 返回值divNumber1和divNumber2都是可空类型, 不能直接调用plus函数, 需要使用“?.”调用plus函数。 事实上由于divNumber1为空值, 代码第②行并没有调用plus函数, 而直接返回空值。 而代码第④行是调用了plus函数进行计算返回结果。

3 非空断言运算符( !!)

可空类型变量可以使用非空断言运算符( !!) 调用非空类型的函数或属性。 非空断言运算符( !!) 顾名思义就是断言可空类型变量不会为空, 调用过程是存在风险的,如果可空类型变量真的为空, 则会抛出空指针异常; 如果非则可以正常调用函数或属性
将上面的代码修改如下:

fun main(args: Array<String>) {
    val divNumber1 = divide(100, 10)
    val result1 = divNumber1!!.plus(100)//divNumber1+100, 结果110.0 ①
    println(result1)
    val divNumber2 = divide(100, 0)
    val result2 = divNumber2!!.plus(100)//divNumber2+100, 结果抛出异常 ②
    println(result2)
}

运行结果:

110.0
Exception in thread "main" kotlin.KotlinNullPointerException
at com.a51work6.Ch6_4_4Kt.main(ch6.4.4.kt:12)

上述代码第①行和第②行都调用plus函数, 代码第①行可以正常调用, 而代码第②行, 由于divNumber2是空值, 非空断言调用会发生异常。

4 使用Elvis运算符( ?:)

有的时候在可空类型表达式中, 当表达式为空值时, 并不希望返回默认的空值, 而是其他数值。 此时可以使用Elvis运算符( ?:) , 也称为空值合并运算符, Elvis运算符有两个操作数, 假设有表达式: A ?: B, 如果A不为空值则结果为A; 否则结果为B。
Elvis运算符经常与安全调用运算符结合使用, 重写上一节示例代码如下

fun main(args: Array<String>) {
    val divNumber1 = divide(100, 0)
    val result1 = divNumber1?.plus(100) ?: 0//divNumber1+100, 结果0 ①
    println(result1)
    val divNumber2 = divide(100, 10)
    val result2 = divNumber2?.plus(100) ?: 0//divNumber2+100, 结果110.0 ②
    println(result2)
}

代码第①行和第②行都是用了Elvis运算符, divNumber1?.plus(100)表达式为空值,则返回0。 divNumber2?.plus(100)表达式不为空值, 则返回110.0。

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