![Kotlin从入门到进阶实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/633/26793633/b_26793633.jpg)
3.4 特殊类型
本节我们介绍Kotlin中的特殊类型:Unit、Nothing、Any及其对应的可空类型Unit?、Nothing?、Any?。
3.4.1 Unit类型
Kotlin也是面向表达式的语言。在Kotlin中所有控制流语句都是表达式(除了变量赋值、异常等)。
Kotlin中的Unit类型实现了与Java中的void一样的功能。总的来说,这个Unit类型并没有什么特别之处。它的定义如下:
![](https://epubservercos.yuewen.com/317ECE/15253386404112206/epubprivate/OEBPS/Images/Figure-P60_6356.jpg?sign=1739524080-fCDa7morNlVXfasVSscCbN1DXcStyZNc-0-f9b739768c9f7f0c0de6306ada1d552c)
不同的是,当一个函数没有返回值的时候,我们用Unit来表示这个特征,而不是null。
大多数时候,我们并不需要显式地返回Unit,或者声明一个函数的返回类型为Unit。编译器会推断出它。代码示例如下:
![](https://epubservercos.yuewen.com/317ECE/15253386404112206/epubprivate/OEBPS/Images/Figure-P61_41531.jpg?sign=1739524080-ZC8u52wjXVIiBzBDwCCIf1cadZ1Gq4Q5-0-bbc925d7c8b1320210d7d361ccaf4d9c)
可以看出,变量helloUnit的类型是kotlin.Unit。下面几种写法是等价的:
![](https://epubservercos.yuewen.com/317ECE/15253386404112206/epubprivate/OEBPS/Images/Figure-P61_41532.jpg?sign=1739524080-o6ZcRp5ZbVOUXG7jzQtXRHoGES59cFLz-0-91c013770ed0d7523fbf0da8ac03fe38)
跟其他类型一样,Kotlin.Unit父类型是Any。如果是一个可空的Unit?,那么父类型是Any?。Unit类型层次结构如图3-3所示。
![](https://epubservercos.yuewen.com/317ECE/15253386404112206/epubprivate/OEBPS/Images/Figure-P61_6562.jpg?sign=1739524080-zeDfJwaRJYxkCRmKNXi63UdiKVoxmRWI-0-32c2a803ae96d7c63860630fbae6dedd)
图3-3 Unit类型层次结构
3.4.2 Nothing与Nothing?类型
在Java中,void不能是变量的类型,也不能作为值打印输出。但是在Java中有个包装类Void是void的自动装箱类型。如果你想让一个方法的返回类型永远是null的话,可以把返回类型置为这个大写的Void类型。
代码示例如下:
![](https://epubservercos.yuewen.com/317ECE/15253386404112206/epubprivate/OEBPS/Images/Figure-P62_41696.jpg?sign=1739524080-08jMEz2n8NIQr9uQRGHJ6MYctJi7iJm6-0-f1e416ab8c87dc4b0eecac0d47a2157e)
测试代码如下:
![](https://epubservercos.yuewen.com/317ECE/15253386404112206/epubprivate/OEBPS/Images/Figure-P62_41695.jpg?sign=1739524080-DjGHXf3EQsDUn0BxCXnQyrWn3hwWoGiI-0-5fb14c84ba9e86c2c4d4d7c2ebb92d9d)
这个Void对应Kotlin中的Nothing?,其唯一可被访问的返回值也是null。
如3.13节中的Kotlin类型层次结构图(图3-2)所示,在Kotlin类型层次结构的最底层就是Nothing类型,Nothing类型层次结构如图3-4所示。
![](https://epubservercos.yuewen.com/317ECE/15253386404112206/epubprivate/OEBPS/Images/Figure-P62_41624.jpg?sign=1739524080-wIeO5KszHwVtyu2ALL9vUijCIJr2Le00-0-15b33e41beac4bb6499e549db2c06eda)
图3-4 Nothing类型层次结构
Nothing类的定义如下:
public class Nothing private constructor() //Nothing的构造函数是private的,外界无法创建Nothing对象
这个Nothing()不能被实例化:
>>> Nothing() is Any //不能实例化,因为默认的主构造函数是私有的 error: cannot access '<init>': it is private in 'Nothing' Nothing() is Any ^
从上面的代码示例中可以看出Nothing()不可被访问。如果一个函数的返回值是Nothing,就意味着这个函数永远不会有返回值。
但是我们可以使用Nothing来表达一个从来不存在的返回值。例如EmptyList中的get()函数
internal object EmptyList : List<Nothing>, Serializable, RandomAccess { override fun get(index: Int): Nothing = throw IndexOutOfBoundsException ("Empty list doesn't contain element at index $index.") //get 函数的返回类型是Nothing } }
一个空的List调用get()函数,直接抛出了IndexOutOfBoundsException,这个时候可以使用Nothing作为这个get()函数的返回类型,因为它永远不会返回某个值,而是直接抛出了异常。
再例如Kotlin标准库里面的exitProcess()函数:
![](https://epubservercos.yuewen.com/317ECE/15253386404112206/epubprivate/OEBPS/Images/Figure-P63_41698.jpg?sign=1739524080-hr35ZeWhaf6Cb5KHdFHwdx6rZLHpat7B-0-5f9d0e76801a97e0b9e2de8534c9d2f4)
注意:Unit与Nothing之间的区别是,Unit类型表达式计算结果的返回类型是Unit; Nothing类型的表达式计算结果是永远不会返回的(与Java中的void相同)。
Nothing?可以只包含一个值null。代码示例如下:
![](https://epubservercos.yuewen.com/317ECE/15253386404112206/epubprivate/OEBPS/Images/Figure-P63_41699.jpg?sign=1739524080-igQNJMTwEJefg5CqXhWFGPPFK3YUFOu1-0-d5c5f204c3d40158cc515e8a1f7f90bb)
从上面的代码示例中可以看出:Nothing?唯一允许的值是null,可被用作任何可空类型的空引用。
3.4.3 Any与Any?类型
就像Any是在非空类型层次结构的根一样,Any?是可空类型层次的根。Any?是Any的超集,Any?是Kotlin类型层次结构的最顶端。Any类型层次结构如图3-5所示。
![](https://epubservercos.yuewen.com/317ECE/15253386404112206/epubprivate/OEBPS/Images/Figure-P63_6873.jpg?sign=1739524080-55iptjiwWkS4hxKCoaGqCpJYKxirChA0-0-3b255d6fe73b7b53f89960aca5362a1d)
图3-5 Any类型层次结构
代码示例:
![](https://epubservercos.yuewen.com/317ECE/15253386404112206/epubprivate/OEBPS/Images/Figure-P64_41701.jpg?sign=1739524080-dhqfvPnXeO65wpFn8xWZG4sMx4mTEaJO-0-58339b6b7575ac8057e4da43d0a02e5c)