学习Kotlin之面向对象编程基础(二)
空指针检查
Android系统上崩溃率最高的异常类型就是空指针异常。即使是如此简单的一小段代码,都有产生空指针异常的潜在风险。
可空类型系统
Kotlin却非常科学地解决了这个问题,它利用编译时判空检查的机制几乎杜绝了空指针异常。
Kotlin提供了一系列的辅助工具,让我们能轻松地处理各种判空情况。
如下函数:
这段代码实际上是没有空指针风险的,因为Kotlin默认所有的参数和变量都不可为空,所以这里传入的Study参数也一定不会为空,我们可以放心地调用它的任何函数。
如果你尝试向doStudy()函数传入一个null参数,就会提示错误,Kotlin将空指针异常的检查提前到了编译时期,这样就可以保证程序在运行时期不会出现空指针异常了。
如果我们需要某个参数或者变量为空,就要使用Kotlin提供的可为空的类型系统,我们需要在编译时期就将所有潜在的空指针异常都处理掉,否则代码将无法编译通过。
那么可为空的类型系统是什么样的呢?
其实就是在类名的后面加上一个问号。
比如,Int表示不可为空的整型,而Int?就表示可为空的整型;String表示不可为空的字符串,而String?就表示可为空的字符串。
回到刚才的doStudy()函数,如果希望传入的参数为空,就把参数类型由Study改成Study?
由于我们将参数改成了可为空的Study?类型,此时调用参数的readBooks()和doHomework()方法都可能造成空指针异常,因此Kotlin在这种情况下不允许编译通过。
解决方法:只要把空指针异常都处理掉就可以了。比如做个判断处理。
判空辅助工具
?.操作符
就是当对象不为空时正常调用相应的方法,当对象为空时则什么都不做。
比如以下的判空处理代码:
使用?.操作符就可以简化成:
对doStudy()函数进行优化:
?:操作符。
这个操作符的左右两边都接收一个表达式,如果左边表达式的结果不为空就返回左边表达式的结果,否则就返回右边表达式的结果。
观察如下代码:
使用?:操作符就可以简化成:
比如现在我们要编写一个函数用来获得一段文本的长度。
借助操作符让它变得简单:
首先由于text是可能为空的,因此我们在调用它的length字段时需要使用?.操作符,而当text为空时,text?.length会返回一个null值,这个时候我们再借助?:操作符让它返回0。
不过有的时候我们可能从逻辑上已经将空指针异常处理了,但是Kotlin的编译器并不知道,这个时候它还是会编译失败。
在这种情况下,如果我们想要强行通过编译,可以使用非空断言工具,写法是在对象的后面加上!!,如下所示:
这是一种有风险的写法,意在告诉Kotlin,我非常确信这里的对象不会为空,所以不用做空指针检查了。
let
let既不是操作符,也不是什么关键字,而是一个函数。
这个函数提供了函数式API的编程接口,并将原始调用对象作为参数传递到Lambda表达式中。
这里调用了obj对象的let函数,然后Lambda表达式中的代码就会立即执行,并且这个obj对象本身还会作为参数传递到Lambda表达式中。不过,为了防止变量重名,这里将参数名改成了obj2,但实际上它们是同一个对象,这就是let函数的作用。
let函数属于Kotlin中的标准函数,它的特性配合?.操作符可以在空指针检查的时候起到很大的作用。
回到doStudy()函数,目前的代码如下所示:
将这段代码准确翻译成使用if判断语句的写法,对应的代码如下:
问题有:本来我们进行一次if判断就能随意调用study对象的任何方法,但受制于?.操作符的限制,现在变成了每次调用study对象的方法时都要进行一次if判断。
这个时候就可以结合使用?.操作符和let函数来对代码进行优化了,如下所示:
?.操作符表示对象为空时什么都不做,对象不为空时就调用let函数,而let函数会将study对象本身作为参数传递到Lambda表达式中,此时的study对象肯定不为空了,我们就能放心地调用它的任意方法了。
由于Lambda表达式的语法特性,当Lambda表达式的参数列表中只有一个参数时,可以不用声明参数名,直接使用it关键字来代替即可,那么代码就可以进一步简化成:
let函数是可以处理全局变量的判空问题的,而if判断语句则无法做到这一点。
比如我们将doStudy()函数中的参数变成一个全局变量,使用let函数仍然可以正常工作,但使用if判断语句则会提示错误,
原因是:全局变量的值随时都有可能被其他线程所修改,即使做了判空处理,仍然无法保证if语句中的study变量没有空指针风险。
字符串内嵌表达式
Java并不支持。在Kotlin中,我们不需要再像使用Java时那样拼接字符串了,而是可以直接将表达式写在字符串里面。
语法规则:
另外,当表达式中仅有一个变量的时候,还可以将两边的大括号省略,如下所示:
函数的参数默认值
我们可以在定义函数的时候给任意参数设定一个默认值,这样当调用此函数时就不会强制要求调用方为此参数传值,在没有传值的情况下会自动使用参数的默认值。
我们可以通过键值对的方式来传参:
此时哪个参数在前哪个参数在后都无所谓,Kotlin可以准确地将参数匹配上。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】