企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
### **?(可空类型变量)** 我们需要知道,Kotlin把变量分成了两种类型,一种是不可空类型,一种可空类型。**变量默认是非空类型,除非显示地把它标记为可空**。那可空类型变量怎么定义呢?**只需在变量类型后面加上一个问号,变量就变成了可空类型变量**,当某个变量的值可以为空时,必须在声明处的数据类型后添加“?”来标识该引用可为空。参考代码: ~~~ fun main(args: Array<String>) { //非空类型变量 var price: String //可空类型变量 var age: String? } ~~~ 针对以上代码,其中price是非空类型变量,其中age是可空类型变量。 1. Kotlin官方约定变量默认为非空类型时,该变量不能赋值为null,age为null时,编译可以通过。 2. 在使用可空变量时,如果不知道该变量的初始值,则需要将其赋值为null,否则会报“variable 'age' must be initialized”异常。 >[info]注意:问号可以加在任何类型的后面来表示这个类型的变量可以存储null引用:String?、Int?、MyCustomType?等等,没有问号的类型表示这种类型的变量不能存储null 引用。这说明所有常见类型默认都是非空的,除非显式地把它标记为可空。 一旦你有一个可空类型的值,能对它进行的操作也会受到限制,比如不能再随意调用它的方法,也不能把它赋值给非空类型的变量,也不能把可空类型的值传给拥有非空类型参数的函数;最重要的操作就是和null 进行比较。而且一旦你进行了比较操作,编译器就会记住,并且在这次比较发生的作用域内把这个值当作非空来对待。 **一、不可空变量不能赋值为null**,如果我们给price以及age两个变量都赋值为null,将出现编译错误,参考截图: ![](https://i.loli.net/2019/04/20/5cba08e7319be.png) 可以看到,代码提示`“Null can not be a value of a non-null type String”`也就是“**非空类型的String不能赋值为null**”。 **二、可空类型变量不能直接使用**,如果我们直接使用可空类型变量age,则会出现如下的编译错误,参考代码: ![](https://i.loli.net/2019/04/20/5cba096ea4b4f.png) 是的,编译的时候错误提示`“Only safe(?.) or non-null asserted(!!.) calls are allowed ona nullable receiver of type String?”`,也就是“**可以通过安全调用符(?.)或者非空断言(!!.)直接去使用可空类型的变量**”。 这里其实编译器帮我们提示了2种做法。其实想要使用可空类型变量,总结起来使用3种方式的,汇总如下: * 方式1:使用非空判断 * 方式2:使用安全操作符“?.” * 方式3:使用非空断言"!!" **使用非空判断使用可空类型变量**,比如针对上面代码,我们在使用age变量的时候通过非空判断去使用,参考如下: ~~~ fun main(args: Array<String>) { //非空类型变量 var price: String //可空类型变量 var age: String? = null //直接使用age //非空判断,Java里面的做法 if (age != null) { age.toInt() } } ~~~ 可以看到,编译通过了。因为**Kotlin约定“如果一个变量,进行了非空判断,该变量的类型就变成了非空类型"**。”也**就是经过了代码的9行,到了代码的10行,编译器会认为age变量是不可空类型变量了**。 虽然非空判断,就可以使用可空类型的变量了,但是如果都用非空判断,代码里面将会出现大量的非空判断。这样的代码看起来就很像java的做法了。【**Kotlin相比于Java,代码中减少了非空判断的使用**】。那毫无疑问,**不用非空判断,就需要用到Kotlin提供的安全调用符或者非空断言**。 >[info]注意:可空的和非空的对象在运行时没有什么区别;可空类型并不是非空类型的包装。所有的检查都发生在编译期。这意味着使用Kotlin 的可空类型并不会在运行时带来额外的开销。 示例 ``` fun main(args: Array<String>) { var name: String = "Tom" //非空变量 var telephone: String? = null //可空变量 if (telephone != null) { print(telephone.length) } else { telephone = "18800008888" print("telephone =" + telephone) } } ``` 运行结果 ``` telephone =18800008888 ```