先拿一段java代码举个例子
ArrayList<String> list = null; System.out.println("size="+list.size());上述操作在打印集合的size时是肯定会包空指针异常的,那么将上面的代码转换成kotlin的代码
val list: ArrayList<String>? = null println("size=" + list!!.size)可以看到之前的java代码转换成kotlin之后,可以看到,声明语句的类型后面加了一个“?”,代表该对象可以为null,紧跟着将变量赋值为null,如果将“?”去掉,这样写是编译不通过的;打印语句里的list后面加上了“!!”。然而,执行的结果和java代码一样是报空指针,到这里就印证了第二条概念了。那如果去掉“!!”会发生什么呢?对不起,编译不通过! 现在把“!!”换成“?”,来看看会有什么变化
val list: ArrayList<String>? = null println("size=" + list?.size)执行结果并没有报错,size 为 null。但是如果我们需要在判断list为null时,不抛出异常,而是返回一个确切的值,那该怎么做呢?比如下面的情况
val list: ArrayList<String>? = null if (list?.size > 0) { println("size > 0") }此时的list是必定为null的,编译器会告诉我们 “Operator call corresponds to a dot-qualified call ‘list?.size.compareTo(0)’ which is not allowed on a nullable receiver 'list?.size’”,大概意思就是list.size的值可为空,与0做比较的做法不合理。而编译器的建议是在list?.size后面加上“!!”,但是这样就不就肯定会抛异常了! 这里我们可以定义一个变量赋值为0,然后判断如果list不为空,则将size赋值给变量,再用这个变量与0相比较。这个方法是可行的,不过这里可以使用更便捷的方法,就是:“ ?:”,用法 :**对象A ?: 对象B ** 。表示的意思是,当对象A值为null的时候,那么它就会返回后面的对象B。再看如下代码
val list: ArrayList<String>? = null if (list?.size ?:0 > 0) { println("size > 0") }意思是当list为null时返回0。相当于java中的
list == null ? 0 : list.size();