17.2 基础类型
不仅可以在 Scala 中使用 Java 的任何类型,
而且同时也可以享受到由 Scala 提供的一些原生类型。
Any类型
scala 的 Any 类型的所有超类型.

Any 类型可以作为任意类型对象的一个通用引用。
Any 是一个抽象类,定义了如下方 法:
!=()
##()
==()
asInstanceOf
equals()
hashCode()
isInstanceOf
toString()
getClass()
AnyVal和AnyRef
Any 类型的直接后裔是 AnyVal 和 AnyRef 类型。
AnyVal 是 Scala 中所有值类型(如 Int、Double 等)的基础类型,并映射到了 Java 中的原始类型,
而 AnyRef 是所有引用类型的基础类型。
尽管 AnyVal 没有什么额外的方法,但是 AnyRef 包含了 Java 的 Object 的方法,如 notify()、wait()、finalize()等。
Any 类型位于类型层次结构的最顶层,而最底层的类型是 Nothing。
Nothin类型
在 Scala 中,Nothing 是一切类型的子类型。
我们很容易明白我们为何需要 Any 类型,但是 Nothing 类型在一开始看起来相当奇怪,特别是因为它代表了任何类型的子类型。
Nothing 类型在 Scala 的类型验证机制的支持上意义重大。
Scala 的类型推断尽可能地 确定表达式和方法的类型。如果推断出的类型太过宽泛,则不利于类型验证。
同时,我们确实也希望可以推断这样的表达式或函数的类型,例如: 在分支中, 其一个分支可以返回,如 Int 类型的结果, 而另一个分支抛出异常.
def someOp(number: Int) = {
if (number < 10)
number * 2
else
throw new RuntimeException("invalid argument")
}
在前面这种情况下,将该函数的返回类型推断为 Any 类型则太宽泛了,而且也没有什么用, 而将返回类型推断为 Int 则更为有用。
我们可以很容易地看出该算术表达式的计算结果类型为 Int。
此外,也必须要推断抛出异常的分支的结果类型,在这种情况下,需要为其返回一个 Int 类型或者 Int 类型的子类型,以便使其和推断的返回类型兼容。
但是,throw 语句的结果类型不能被推断为 Int 类型而被任意处理, 因为在任何地方都可能会引发异常。 Nothing 类型这时候就派上用场了—--通过作为所有类型的子类型,它使类型推断过程得以顺利进行。
因为Nothing是所有类型的子类型,所以它可以替代任何东西。
Nothing 是抽象的,因此在运行时永远都不会得到一个真正的 Nothing 实例。
Option类型
Java 的空指针异常是所有程序员的梦魇. Java 之父曾经也说过 null的设计师他的一个错误.
在 Joshua Bloch 的 Effective Java[Blo08] 一书中有这样的合理建议: 返回空集合,而不是 null 引用。
如果遵循这个建议,我们就不必忍受 NullPointerException 了。
即使结果 集合为空,迭代也会变得很容易。在使用集合的时候,这是很好的建议,但是在使用其他返回类型时,我们也需要类似的内容。
例如,在执行模式匹配时,匹配的结果可能是对象、列表、元组等,也可能不存在。从两方面来说,悄无声息地返回一个 null 是有问题的。
- 首先,可能没有结果值这个事实并没有被明确地(通过类型)表示出来。
- 其次,没有办法强制要求函数的调用者来检查是不存在 还是
null。
Scala 进一步指定了可能的不存在性。使用 Scala 的 Option[T],可以进行有意图的编程,并指定打算不返回结果。
Scala 以类型安全的方式实现了这一点,因此可以在编译时强制 进行检查。
Option有两个子类:Some和None
当返回类型是Option的时候, 其实就是在告诉调用者: 哥们, 返回的值中有可能有null你要小心了.
object Test {
def commentOnPractice(input: String) = { // 而不是返回 null
if (input == "test")
Some("good")
else
None
}
def main(args: Array[String]): Unit = {
for (input <- Set("test", "hack")) {
val comment = commentOnPractice(input)
// 如果返回的是None, 则把参数返回
val commentDisplay = comment.getOrElse("Found no comments")
println(s"input: $input comment: $commentDisplay")
}
}
}
Either类型
当一个函数调用的结果可能存在也可能不存在时,Option 类型很有用。
有时候,你可能希望从一个函数中返回两种不同类型的值之一。
这个时候,Scala 的 Either 类型就派上用场了。
Either本身是个抽象类, 他有两个直接的实现子类: Left和Right
左值(Left)(通常被认为是错误)和右值(Right)(通常被认为是正确的或者符合预期的值)。
object Test {
def compute(input: Int): Either[String, Double] = {
if (input > 0)
Right(math.sqrt(input))
else
Left("Error computing, invalid input")
}
def displayResult(result: Either[String, Double]): Unit = {
result match {
case Left(value) => println(s"result = $value")
case Right(error) => println(s"error = $error")
}
}
def main(args: Array[String]): Unit = {
// 使用模式匹配来取出其中的值
displayResult(compute(10))
displayResult(compute(-10))
}
}