Kotlin笔记05(空指针检查,小技巧)

  1. 1. 空指针检查
    1. 1.1. 可空类型系统
    2. 1.2. ?.操作符
    3. 1.3. ?:操作符
    4. 1.4. !!.操作符
    5. 1.5. let函数
  2. 2. Kotlin的小技巧
    1. 2.1. 字符串内嵌表达式
    2. 2.2. 函数的参数默认值

空指针检查

Android系统中,最常见的崩溃问题就是空指针异常,相信其他的系统或者程序,也会常常备受空指针问题的影响。这类问题只能由程序员自己主动通过逻辑判断来避免。可是,很难做到完全考虑到所有潜在的空指针异常。

Kotlin的做法则是将空指针异常检查提前到了编译期,在程序员写程序的时候,时刻能够检测出潜在的空指针问题,及时进行处理。

举例:

java代码

1
2
3
4
public void doStudy(Study study){
study.doHomework();
study.readBooks();
}

这段代码java编译肯定没问题,但是他安全么?不一定。如果这个方法当中传入是一个null,将会导致空指针异常。

修改一下:

1
2
3
4
5
6
7
public void doStudy(Study study){
if(study != null){
study.doHomework();
study.readBooks();
}

}

这样才会安全。

转到kotlin:

1
2
3
4
fun doStudy(study:Study){
study.doHomework()
study.readBooks()
}

对于kotlin来说,这是没有问题的,没有空指针的风险。因为,在kotlin当中,默认所有参数和变量都不能为空,所以这里传进来的study一定不为空。可以放心的调用它,一旦传入null,在编译的时候直接报错。

可空类型系统

1
2
3
4
5
6
7
fun doStudy(study:Study?){
//此时study可以为空,但是为空调用会导致空异常,因此加个判断即可
if(study != null){
study.doHomework()
study.readBooks()
}
}

对于业务逻辑需要参数为null的话,kotlin提供的方法是,在参数类名后面加?号,但是函数里参数也是会被检测的,必须要有空的判断。

?.操作符

?.操作符:当对象不为空时正常调用,当为空时什么都不做。

1
2
3
4
5
//上面的代码可以由?.操作符简化为
fun doStudy(study:Study?){
study?.doHomework()
study?.readBooks()
}

?:操作符

?:操作符:左右两边都接收一个表达式,如果左边结果不为空就返回左边结果,否则返回右边表达式结果

1
2
3
4
5
6
7
val a = null
val b = 1
val c = if (a != null){
a
}else{
b
}

相当于:

1
val c = a ?: b

!!.操作符

!!.操作符:非空断言工具,告知kotlin这里的对象不会为空,不用它做非空检查。出错可以抛异常。

1
2
3
4
fun doStudy(study:Study?){
study!!.doHomework()
study!!.readBooks()
}

这个就和java的那个版本一样了,不安全了,照样运行报错了。

let函数

obj对象调用let函数,obj本身会作为参数传递到Lambda表达式中,当列表只有一个参数时用it。

用法:

1
2
3
obj.let{ obj2 ->
//编写具体业务逻辑
}

例子:

1
2
3
4
5
6
fun doStudy(study:Study?){
study?.let {
it.doHomework()
it.readBooks()
}
}

let通常是和?.操作符结合,之前的study?.doHomework(),study?.readBooks()两个,相当于每次调用方法都需要对study做了if判空处理,相当麻烦。可以先study?. 如果study不为空就运行let,如果为空就什么都不做。此时let里面的lambda表达式当中的it肯定就不是空的了,因此let当中运行是安全的。

let的另一个优势:

let函数时可以处理全局变量的判空问题,而if语句是无法做到的

1
2
3
4
5
6
7
8
var studyy : Study? = null;
fun doStudy5(){
if (studyy != null){
studyy.doHomework()
studyy.readBooks()
}
}
//会报错。因为studyy是全局变量,随时可能被其他线程修改,不能保证没有空指针风险
1
2
3
4
5
6
7
8
//而let则没问题
var studyy : Study? = null;
fun doStudy5(){
studyy?.let {
it.readBooks()
it.doHomework()
}
}

Kotlin的小技巧

字符串内嵌表达式

Kotlin一开始就支持了字符串内嵌表达式,我们不再需要像java那样傻傻的拼接字符串了。

1
"hello, ${obj.name}. nice to meet you"

当表达式中仅有一个变量的时候,大括号可以省略

1
"hello, $name. nice to meet you"

kotlin的这种方式,不论是易读性易写性方面都比java更胜一筹

函数的参数默认值

简单来说就是,kotlin允许我们在定义函数的时候给任意参数设定一个默认值,这样当调用这个函数的时候不强求传此参数。

1
fun printParams(num:Int, str:String = "hello")

调用的时候可以

1
printParams(123)

当然默认值也可以给第一个参数

1
fun printParams(num:Int = 0, str:String)

那么填一个参数,就默认到num参数上了。问题不大,kotlin提供了键值对的方式来传参

1
printParams(str = "Hello")