kotlin中引入了Type?来表示Type类型是可能为null,这样从编译上避免了很多NPE的发生。
Type? = Type or null
问号?可以加载任何类型后面,表示这个类型的变量可能为null
没有问号?表示这种类型的变量不为null。
对可空类型的操作,kotlin中考虑了NPE的情况,做了一些限制
//可空类型
var name:String? = null
//非空类型
var personName:String = "娃哈哈"
对可空类型的变量调用它的方法必须做null判断,如果左了判断编译器会记住判断结果
var length:Int = if (name != null) name.length else 0
可空类型变量不能直接赋值给非空类型变量
// error
personName = name;
可空类型的值不能传递给非空类型参数
fun getLength(s:String):Int = s.length
//error
getLength(name)
但是可以把非空类型赋值给可空类型变量
//ok
name = personName;
完整实例如下:
fun main(args: Array<String>) {
//可空类型
var name:String? = null
//非空类型
var personName:String = "娃哈哈"
var length:Int = if (name != null) name.length else 0
//error
getLength(name)
//ok
//name = personName;
// error
personName = name;
}
fun getLength(s:String):Int = s.length
安全调用运算符允许把一次null检查和一次方法或者属性调用合并成一个操作。
Xxx?.xxx = if(Xxx != null) Xxx.xxx else null
注意调用结果是可空类型的
我们来改写前面的例子
var len:Int? = name?.length
对于方法的调用也类似,就不举例子了。
与”?.”运算符类似,”?:”接受两个运算数,如果第一个不为null,表达式就是第一个值,否则取第二个值
Xxx?:xxx = if(Xxx != null) Xxx else xxx
注意”?:”经常与”?.”运算符一起调用,因为我们经常有这样一种调用:
如果Xxx不为null,就调用Xxx.A,否则返回一个默认值
实例如下:
var length2:Int = name?.length?:0
单独使用”?:”一般用于可空类型赋值给非空类型
//可空类型
var name:String? = null
//非空类型
var personName:String = "娃哈哈"
personName = name?:""
as用来进行类型转换,在java中如果类型不匹配将会抛异常,在kotlin中为了减少这种异常抛出,如果认为类型不匹配使用as?可以直接返回null。从而减少异常发生
xxx as? Type = if(xxx is Type) xxx as Type else null
as?与?:一起使用,见下面的例子
class People(val name:String,val age:Int){
override fun equals(other: Any?): Boolean {
var another = other as? People?:return false
return another.name == name && another.age == age
}
override fun hashCode(): Int {
return age.hashCode()*31 + name.hashCode()
}
}
非空断言主要用作将任何类型转换为非空类型,如果被转换的值是null,将会抛出NPE异常。
xxx!! = if(xxx != null) xxx else throw NPE
实例如下:
fun ignoreNulls(s:String?){
var str = s!!
println(str.length)
}
如果s为null,将会在var str = s!!抛出NPE异常
关于可空类型还有let函数,扩展等,后续再逐步介绍,或者参考相关文档