Nothing
和Null
是位于类型系统底层的两个特殊类型,
其中**Nothing
是所有其他类型的子类,而Null
是所有引用类型的子类**。
Null
对于大多数语言而言是熟悉的概念。
尽管这些语言通常并没有定义Null
类型,仅仅定义了关键字null
,
用于向引用变量赋值,表示该变量实际上没有值。
Null
在编译器里的实现相当于以下声明:
package scala
abstract final class Null extends AnyRef
为何Null
可以同时为final
和abstract
呢?
因为不允许子类派生以及创建实例,但运行时环境提供了一个实例,就是我们熟悉和喜爱的Null
Null
被明确定义为AnyRef
的一个子类型,但它也是所有AnyRef
类型的子类型。
这是类型系统允许你用null给任何引用类型赋值的正常做法。
另一方面,因为null
不是Anyval
的子类型,所以不可以用null给Int赋值。
于是Scala的null
与Java的null
完全相同,
因为它必须与Java的null共存于JVM。
否则Scala会破坏null
的概念,引起很多潜在的Bug
与此相反,Nothing
在Java中没有类似的概念,但它填补了存在于Java类型系统中的空白。
Nothing
在编译器里的实现相当于以下声明:
pacage scala
abstract final class Nothing extends Any
Nothing
实际上继承了Any
,根据类型系统里的构造规则,Nothing
是所有其他类型的子类,
无论是引用类型不是值类型,换句话说,Nothing
继承了所有一切。
不同于Nul
l,Nothing
没有实例。但Nothing为类型系统提供了两种功能,这有助于实现健壮且类型安全的设计。
Scala为空列表声明了一个专用的类型:Nil
在Java中Niil必须是像List那样的参数化类型,但是很不幸,根据定义Nil不包含任何元素,所以Nil[String]
和Nil[Any]
是不同的类型,虽然实际上并无差别。
Nil
的声明:
package scala.collection.immutable
object Nil extends List[Nothing] with Product with Serializable
Nothing
和Null
被称为底部的类型,因为它们处于类型层次结构的底端。也因为如此,它们是所有类型的子类。
Nothing
的其他用途是:表示终止程序,
如抛出一下异常,
方法???的定义:
package scala
object Predef {
...
def ??? : Nothing = throw enw NotImplementedError
...
}
由于???方法返回了Nothing
,所以它可以被任何其他函数调用,无论该函数的返回值是什么。
scala.sys
包定义了一个exit
方法,用于程序的正常退出,
类似于Java中的System
包的exit
方法,
不过sys.exit
返回的是Nothing
这意味着方声明为它返回 了一个正常的类型,但在必要的时候也可以调用sys.exit
。并通过编译器类型检查。