(译)Kotlin 之 Nothing
Kotlin 中的 Nothing 到底有什么作用?
原文见Kotlin’s Nothing: Its Usefulness in Generics
本文介绍 Kotlin 中 Nothing 类型在泛型中的作用。先来看一个关于链表的具体例子。

这个链表封装了某种类型,不妨称为 T。链表可以是以下任意一种:
- 类型一 -
Node<T>。它包含两个属性,T类型的 payload 和LinkedList<T>类型的 next - 类型二 - 一个空链表
EmptyList
使用 sealed class 用于保证链表要么是类型一要么是类型二。
所以可以写出如下代码:
1 | sealed class LinkedList<out T> { |
如何写空链表有点挑战。考虑到所有的空链表都是一样的,所以空链表由 Kotlin 中的 object 表示。此外,空链表还必须是 LinkedList<T> 的子类。可以尝试如下写法:
1 | sealed class LinkedList<out T> { |
Kotlin 中的 object 不能带类型参数,所以上面代码编译失败。再来尝试去掉空链表的类型参数。
1 | sealed class LinkedList<out T> { |
代码仍然编译失败。第5行代码中的 T 无法解析。必须为这里的 T 规定一个具体的类型。
见文章开头的那张图,T 是 Node.payload 属性的类型。而空链表并不包含任何 Node。所以正确的代码如下:
1 | sealed class LinkedList<out T> { |
Kotlin 中 Nothing 类型到底是什么?在 Kotlin REPL 中运行 println(Nothing::class.java) 命令输出结果如下:
1 | println(Nothing::class.java) |
Kotlin 的 Nothing 其实就是 Java 中的 Void。在 Kotlin 中,Nothing 表示缺少类型。
再来看看为什么不能让 Kotlin 中的函数返回 Nothing?。比如以下代码编译出错:
1 | fun getNothing() = Nothing() // won't compile |
Kotlin 不允许实例化 Nothing。Nothing 的构造方法是私有的。看看 Java 版本的 getNothing():
1 | public class GetVoidExample { |
Java 中 Void 的构造方法也是私有的。Void 同样不能被实例化。我们也不能返回 Void。所以这样看来 Kotlin 中不能返回 Void 是合理的。
总结一下: Kotlin 的 Nothing 其实就是 Java 中的 Void。Kotlin 中 Nothing 用于泛型,表示该泛型不包含任何类型信息,即该类型缺失。