学习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可以准确地将参数匹配上。

 

posted @   PeacefulGemini  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
回顶部
点击右上角即可分享
微信分享提示