Kotlin(十) 空指针检查、字符串内嵌表达式以及函数默认值

空指针检查

我们在之前的章节里,有定义一个Study的类,它有两个函数,一个doHomework(),一个readBooks()。然后我们定义个doStudy函数,来调用它们,代码如下:

Kotlin 复制代码
fun doStudy(study: Study) {
    study.doHomework()
    study.readBooks()
}

这一串代码,看上去会有空指针错误,但实际上是没有的,因为Kotlin默认所有的参数和变量都不可为空,所以这里传入的Study参数也一定不会为空,我们可以放心地调用它的任何函数。如果你尝试传入null,那么编译器会直接报错。

也就是说,Kotlin将空指针异常的检查提前到了编译时期,如果我们的程序存在空指针异常的风险,那么在编译的时候会直接报错,修正之后才能成功运行,这样就可以保证程序在运行时期不会出现空指针异常了。

看到这里,你可能产生了巨大的疑惑,所有的参数和变量都不可为空?这可真是前所未闻的事情,那如果我们的业务逻辑就是需要某个参数或者变量为空该怎么办呢?不用担心,Kotlin提供了另外一套可为空的类型系统,只不过在使用可为空的类型系统时,我们需要在编译时期就将所有潜在的空指针异常都处理掉,否则代码将无法编译通过。

那么可为空的类型系统是什么样的呢?很简单,就是在类名的后面加上一个问号。比如,Int表示不可为空的整型,而Int?就表示可为空的整型;String表示不可为空的字符串,而String?就表示可为空的字符串。

回到刚才的doStudy()函数,如果我们希望传入的参数可以为空,那么就应该将参数的类型由Study改成Study?,如图:

当你在参数加上?之后,发现调用的函数报错了,因为此时调用参数的readBooks()doHomework()方法都可能造成空指针异常,因此Kotlin在这种情况下不允许编译通过。

那么该如何解决呢?很简单,只要把空指针异常都处理掉就可以了,比如做个判断处理,如下所示:

Kotlin 复制代码
fun doStudy(study: Study?) {
    study?.doHomework()
    study?.readBooks()
}

当然还有另外一种写法:

Kotlin 复制代码
fun doStudy(study: Study?) {
    study?.let { 
        it.readBooks()
        it.doHomework()
    }
}

字符串内嵌表达式

首先来看一下Kotlin中字符串内嵌表达式的语法规则:

Kotlin 复制代码
"hello, ${obj.name}. nice to meet you!"

可以看到,Kotlin允许我们在字符串里嵌入${}这种语法结构的表达式,并在运行时使用表达式执行的结果替代这一部分内容。

另外,当表达式中仅有一个变量的时候,还可以将两边的大括号省略,如下所示:

Kotlin 复制代码
"hello, $name. nice to meet you!"

这种字符串内嵌表达式的写法到底有多么方便,我们通过一个具体的例子来学习一下就知道了。在2.5.4小节中,我们用Java编写了一个Cellphone数据类,其中toString()方法里就使用了比较复杂的拼接字符串的写法。这里我将当时的拼接逻辑单独提炼了出来,代码如下:

Kotlin 复制代码
val brand = "Samsung"
val price = 1299.99
println("Cellphone(brand=" + brand + ", price=" + price + ")")

可以看到,上述字符串中一共使用了4个加号连接符,这种写法不仅写起来非常吃力,很容易写错,而且在代码可读性方面也很糟糕。

而使用字符串内嵌表达式的写法就变得非常简单了,如下所示:

Kotlin 复制代码
val brand = "Samsung"
val price = 1299.99
println("Cellphone(brand=$brand, price=$price)")

很明显,这种写法不管是在易读性还是易写性方面都更胜一筹,是Kotlin更加推崇的写法。这个小技巧会给我们以后的开发工作带来巨大的便利。

函数的参数默认值

我们可以在定义函数的时候给任意参数设定一个默认值,这样当调用此函数时就不会强制要求调用方为此参数传值,在没有传值的情况下会自动使用参数的默认值。

给参数设定默认值的方式也很简单,观察如下代码:

Kotlin 复制代码
fun printParams(num: Int, str: String = "hello") {
    println("num is $num , str is $str")
}

可以看到,这里我们给printParams()函数的第二个参数设定了一个默认值,这样当调用printParams()函数时,可以选择给第二个参数传值,也可以选择不传,在不传的情况下就会自动使用默认值。

相关推荐
胡斌附体30 分钟前
qt socket编程正确重启tcpServer的姿势
开发语言·c++·qt·socket编程
白露与泡影1 小时前
Java面试题及答案整理( 2025年 4 月最新版,持续更新)
java·开发语言
YueiL1 小时前
C++入门练习之 给出年分m和一年中的第n天,算出第n天是几月几号
开发语言·c++·算法
冷凝女子1 小时前
【QT】获取文件路径中的文件名,去掉后缀,然后提取文件名中的数字
开发语言·数据库·qt
我不想当小卡拉米1 小时前
C++:继承+菱形虚拟继承的一箭双雕
开发语言·jvm·c++
weixin_457885821 小时前
JavaScript智能对话机器人——企业知识库自动化
开发语言·javascript·自动化
孤独得猿2 小时前
Qt常用控件第一部分
服务器·开发语言·qt
慕斯策划一场流浪2 小时前
fastGPT—nextjs—mongoose—团队管理之团队列表api接口实现
开发语言·前端·javascript·fastgpt env文件配置·fastgpt团队列表接口实现·fastgpt团队切换api·fastgpt团队切换逻辑
时光呢2 小时前
JAVA常见的 JVM 参数及其典型默认值
java·开发语言·jvm
橙橙子2302 小时前
c++柔性数组、友元、类模版
开发语言·c++·柔性数组